Always use 64-bit filesize and file offsets in DCC.
Based on LRN's commit for replacing stat with GFileInfo https://github.com/hexchat/hexchat/commit/32008bb Fixes #382
This commit is contained in:
		
							parent
							
								
									985ea610e6
								
							
						
					
					
						commit
						5152040c17
					
				
					 4 changed files with 331 additions and 192 deletions
				
			
		
							
								
								
									
										474
									
								
								src/common/dcc.c
									
										
									
									
									
								
							
							
						
						
									
										474
									
								
								src/common/dcc.c
									
										
									
									
									
								
							| 
						 | 
					@ -23,8 +23,9 @@
 | 
				
			||||||
 * Jim Seymour (jseymour@LinxNet.com)
 | 
					 * Jim Seymour (jseymour@LinxNet.com)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* we only use 32 bits, but without this define, you get only 31! */
 | 
					/* Required to make lseek use off64_t, but doesn't work on Windows */
 | 
				
			||||||
#define _FILE_OFFSET_BITS 64
 | 
					#define _FILE_OFFSET_BITS 64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
| 
						 | 
					@ -45,6 +46,8 @@
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gio/gio.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "hexchat.h"
 | 
					#include "hexchat.h"
 | 
				
			||||||
#include "util.h"
 | 
					#include "util.h"
 | 
				
			||||||
#include "fe.h"
 | 
					#include "fe.h"
 | 
				
			||||||
| 
						 | 
					@ -57,13 +60,9 @@
 | 
				
			||||||
#include "url.h"
 | 
					#include "url.h"
 | 
				
			||||||
#include "hexchatc.h"
 | 
					#include "hexchatc.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef USE_DCC64
 | 
					/* Setting _FILE_OFFSET_BITS to 64 doesn't change lseek to use off64_t on Windows, so override lseek to the version that does */
 | 
				
			||||||
#define BIG_STR_TO_INT(x) strtoull(x,NULL,10)
 | 
					 | 
				
			||||||
#ifdef WIN32
 | 
					#ifdef WIN32
 | 
				
			||||||
#define stat _stat64
 | 
					#define lseek _lseeki64
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
#define BIG_STR_TO_INT(x) strtoul(x,NULL,10)
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static char *dcctypes[] = { "SEND", "RECV", "CHAT", "CHAT" };
 | 
					static char *dcctypes[] = { "SEND", "RECV", "CHAT", "CHAT" };
 | 
				
			||||||
| 
						 | 
					@ -78,7 +77,7 @@ struct dccstat_info dccstat[] = {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dcc_global_throttle;	/* 0x1 = sends, 0x2 = gets */
 | 
					static int dcc_global_throttle;	/* 0x1 = sends, 0x2 = gets */
 | 
				
			||||||
/*static*/ int dcc_sendcpssum, dcc_getcpssum;
 | 
					static gint64 dcc_sendcpssum, dcc_getcpssum;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct DCC *new_dcc (void);
 | 
					static struct DCC *new_dcc (void);
 | 
				
			||||||
static void dcc_close (struct DCC *dcc, int dccstat, int destroy);
 | 
					static void dcc_close (struct DCC *dcc, int dccstat, int destroy);
 | 
				
			||||||
| 
						 | 
					@ -127,11 +126,12 @@ static void
 | 
				
			||||||
dcc_calc_cps (struct DCC *dcc)
 | 
					dcc_calc_cps (struct DCC *dcc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	GTimeVal now;
 | 
						GTimeVal now;
 | 
				
			||||||
	int oldcps;
 | 
						gint64 oldcps;
 | 
				
			||||||
	double timediff, startdiff;
 | 
						double timediff, startdiff;
 | 
				
			||||||
	int glob_throttle_bit, wasthrottled;
 | 
						int glob_throttle_bit, wasthrottled;
 | 
				
			||||||
	int *cpssum, glob_limit;
 | 
						gint64 *cpssum;
 | 
				
			||||||
	DCC_SIZE pos, posdiff;
 | 
						int glob_limit;
 | 
				
			||||||
 | 
						goffset pos, posdiff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	g_get_current_time (&now);
 | 
						g_get_current_time (&now);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -169,8 +169,7 @@ dcc_calc_cps (struct DCC *dcc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		posdiff = pos - dcc->lastcpspos;
 | 
							posdiff = pos - dcc->lastcpspos;
 | 
				
			||||||
		oldcps = dcc->cps;
 | 
							oldcps = dcc->cps;
 | 
				
			||||||
		dcc->cps = ((double) posdiff / timediff) * (timediff / startdiff) +
 | 
							dcc->cps = (gint64) ((posdiff / timediff) * (timediff / startdiff) + dcc->cps * (1.0 - (timediff / startdiff)));
 | 
				
			||||||
			(double) dcc->cps * (1.0 - (timediff / startdiff));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		*cpssum += dcc->cps - oldcps;
 | 
							*cpssum += dcc->cps - oldcps;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -420,7 +419,7 @@ dcc_close (struct DCC *dcc, int dccstat, int destroy)
 | 
				
			||||||
		if (dcc->proxy)
 | 
							if (dcc->proxy)
 | 
				
			||||||
			free (dcc->proxy);
 | 
								free (dcc->proxy);
 | 
				
			||||||
		if (dcc->file)
 | 
							if (dcc->file)
 | 
				
			||||||
			free (dcc->file);
 | 
								g_free (dcc->file);
 | 
				
			||||||
		if (dcc->destfile)
 | 
							if (dcc->destfile)
 | 
				
			||||||
			g_free (dcc->destfile);
 | 
								g_free (dcc->destfile);
 | 
				
			||||||
		free (dcc->nick);
 | 
							free (dcc->nick);
 | 
				
			||||||
| 
						 | 
					@ -700,11 +699,17 @@ dcc_read (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (dcc->resumable)
 | 
							if (dcc->resumable)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			dcc->fp = g_open (dcc->destfile, O_WRONLY | O_APPEND | OFLAGS, 0);
 | 
								gchar *filename_fs = g_filename_from_utf8(dcc->destfile, -1, NULL, NULL, NULL);
 | 
				
			||||||
 | 
								dcc->fp = g_open(dcc->destfile, O_WRONLY | O_APPEND | OFLAGS, 0);
 | 
				
			||||||
 | 
								g_free (filename_fs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			dcc->pos = dcc->resumable;
 | 
								dcc->pos = dcc->resumable;
 | 
				
			||||||
			dcc->ack = dcc->resumable;
 | 
								dcc->ack = dcc->resumable;
 | 
				
			||||||
		} else
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								gchar *filename_fs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (g_access (dcc->destfile, F_OK) == 0)
 | 
								if (g_access (dcc->destfile, F_OK) == 0)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				n = 0;
 | 
									n = 0;
 | 
				
			||||||
| 
						 | 
					@ -713,7 +718,7 @@ dcc_read (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
 | 
				
			||||||
					n++;
 | 
										n++;
 | 
				
			||||||
					snprintf (buf, sizeof (buf), "%s.%d", dcc->destfile, n);
 | 
										snprintf (buf, sizeof (buf), "%s.%d", dcc->destfile, n);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				while (access (buf, F_OK) == 0);
 | 
									while (g_access (buf, F_OK) == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				old = dcc->destfile;
 | 
									old = dcc->destfile;
 | 
				
			||||||
				dcc->destfile = g_strdup (buf);
 | 
									dcc->destfile = g_strdup (buf);
 | 
				
			||||||
| 
						 | 
					@ -722,9 +727,10 @@ dcc_read (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
 | 
				
			||||||
								 old, dcc->destfile, NULL, NULL, 0);
 | 
													 old, dcc->destfile, NULL, NULL, 0);
 | 
				
			||||||
				g_free (old);
 | 
									g_free (old);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			dcc->fp =
 | 
					
 | 
				
			||||||
				g_open (dcc->destfile, OFLAGS | O_TRUNC | O_WRONLY | O_CREAT,
 | 
								filename_fs = g_filename_from_utf8 (dcc->destfile, -1, NULL, NULL, NULL);
 | 
				
			||||||
						prefs.hex_dcc_permissions);
 | 
								dcc->fp = g_open (filename_fs, OFLAGS | O_TRUNC | O_WRONLY | O_CREAT, prefs.hex_dcc_permissions);
 | 
				
			||||||
 | 
								g_free (filename_fs);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (dcc->fp == -1)
 | 
						if (dcc->fp == -1)
 | 
				
			||||||
| 
						 | 
					@ -792,7 +798,7 @@ dcc_read (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
 | 
				
			||||||
			dcc_close (dcc, STAT_DONE, FALSE);
 | 
								dcc_close (dcc, STAT_DONE, FALSE);
 | 
				
			||||||
			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 */
 | 
								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 */
 | 
				
			||||||
			/* cppcheck-suppress deallocuse */
 | 
								/* cppcheck-suppress deallocuse */
 | 
				
			||||||
			sprintf (buf, "%d", dcc->cps);
 | 
								sprintf (buf, "%" G_GINT64_FORMAT, dcc->cps);
 | 
				
			||||||
			EMIT_SIGNAL (XP_TE_DCCRECVCOMP, dcc->serv->front_session,
 | 
								EMIT_SIGNAL (XP_TE_DCCRECVCOMP, dcc->serv->front_session,
 | 
				
			||||||
							 dcc->file, dcc->destfile, dcc->nick, buf, 0);
 | 
												 dcc->file, dcc->destfile, dcc->nick, buf, 0);
 | 
				
			||||||
			return TRUE;
 | 
								return TRUE;
 | 
				
			||||||
| 
						 | 
					@ -1416,8 +1422,8 @@ dcc_connect (struct DCC *dcc)
 | 
				
			||||||
		/* possible problems with filenames containing spaces? */
 | 
							/* possible problems with filenames containing spaces? */
 | 
				
			||||||
		if (dcc->type == TYPE_RECV)
 | 
							if (dcc->type == TYPE_RECV)
 | 
				
			||||||
			snprintf (tbuf, sizeof (tbuf), strchr (dcc->file, ' ') ?
 | 
								snprintf (tbuf, sizeof (tbuf), strchr (dcc->file, ' ') ?
 | 
				
			||||||
					"DCC SEND \"%s\" %u %d %"DCC_SFMT" %d" :
 | 
										"DCC SEND \"%s\" %u %d %" G_GUINT64_FORMAT " %d" :
 | 
				
			||||||
					"DCC SEND %s %u %d %"DCC_SFMT" %d", dcc->file,
 | 
										"DCC SEND %s %u %d %" G_GUINT64_FORMAT " %d", dcc->file,
 | 
				
			||||||
					dcc->addr, dcc->port, dcc->size, dcc->pasvid);
 | 
										dcc->addr, dcc->port, dcc->size, dcc->pasvid);
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			snprintf (tbuf, sizeof (tbuf), "DCC CHAT chat %u %d %d",
 | 
								snprintf (tbuf, sizeof (tbuf), "DCC CHAT chat %u %d %d",
 | 
				
			||||||
| 
						 | 
					@ -1463,7 +1469,7 @@ dcc_send_data (GIOChannel *source, GIOCondition condition, struct DCC *dcc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!dcc->fastsend)
 | 
						if (!dcc->fastsend)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (dcc->ack < dcc->pos)
 | 
							if (dcc->ack < (dcc->pos & 0xFFFFFFFF))
 | 
				
			||||||
			return TRUE;
 | 
								return TRUE;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else if (!dcc->wiotag)
 | 
						else if (!dcc->wiotag)
 | 
				
			||||||
| 
						 | 
					@ -1538,7 +1544,7 @@ dcc_handle_new_ack (struct DCC *dcc)
 | 
				
			||||||
		dcc_close (dcc, STAT_DONE, FALSE);
 | 
							dcc_close (dcc, STAT_DONE, FALSE);
 | 
				
			||||||
		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 */
 | 
							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 */
 | 
				
			||||||
		/* cppcheck-suppress deallocuse */
 | 
							/* cppcheck-suppress deallocuse */
 | 
				
			||||||
		sprintf (buf, "%d", dcc->cps);
 | 
							sprintf (buf, "%" G_GINT64_FORMAT, dcc->cps);
 | 
				
			||||||
		EMIT_SIGNAL (XP_TE_DCCSENDCOMP, dcc->serv->front_session,
 | 
							EMIT_SIGNAL (XP_TE_DCCSENDCOMP, dcc->serv->front_session,
 | 
				
			||||||
						 file_part (dcc->file), dcc->nick, buf, NULL, 0);
 | 
											 file_part (dcc->file), dcc->nick, buf, NULL, 0);
 | 
				
			||||||
		done = TRUE;
 | 
							done = TRUE;
 | 
				
			||||||
| 
						 | 
					@ -1548,12 +1554,10 @@ dcc_handle_new_ack (struct DCC *dcc)
 | 
				
			||||||
		dcc_send_data (NULL, 0, (gpointer)dcc);
 | 
							dcc_send_data (NULL, 0, (gpointer)dcc);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef USE_DCC64
 | 
					 | 
				
			||||||
	/* take the top 32 of "bytes send" and bottom 32 of "ack" */
 | 
						/* take the top 32 of "bytes send" and bottom 32 of "ack" */
 | 
				
			||||||
	dcc->ack = (dcc->pos & G_GINT64_CONSTANT (0xffffffff00000000)) |
 | 
						dcc->ack = (dcc->pos & G_GINT64_CONSTANT (0xffffffff00000000)) |
 | 
				
			||||||
					(dcc->ack & 0xffffffff);
 | 
										(dcc->ack & 0xffffffff);
 | 
				
			||||||
	/* dcc->ack is only used for CPS and PERCENTAGE calcs from now on... */
 | 
						/* dcc->ack is only used for CPS and PERCENTAGE calcs from now on... */
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return done;
 | 
						return done;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1762,7 +1766,7 @@ dcc_listen_init (struct DCC *dcc, session *sess)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct session *dccsess;
 | 
					static struct session *dccsess;
 | 
				
			||||||
static char *dccto;				  /* lame!! */
 | 
					static char *dccto;				  /* lame!! */
 | 
				
			||||||
static int dccmaxcps;
 | 
					static gint64 dccmaxcps;
 | 
				
			||||||
static int recursive = FALSE;
 | 
					static int recursive = FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
| 
						 | 
					@ -1772,21 +1776,25 @@ dcc_send_wild (char *file)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
dcc_send (struct session *sess, char *to, char *file, int maxcps, int passive)
 | 
					dcc_send (struct session *sess, char *to, char *filename, gint64 maxcps, int passive)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char outbuf[512];
 | 
						char outbuf[512];
 | 
				
			||||||
	GStatBuf st;
 | 
						GFileInfo *file_info;
 | 
				
			||||||
 | 
						GFile *file;
 | 
				
			||||||
	struct DCC *dcc;
 | 
						struct DCC *dcc;
 | 
				
			||||||
 | 
						gchar *filename_fs;
 | 
				
			||||||
 | 
						GFileType file_type;
 | 
				
			||||||
 | 
						goffset file_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	file = expand_homedir (file);
 | 
						filename = expand_homedir (filename);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!recursive && (strchr (file, '*') || strchr (file, '?')))
 | 
						if (!recursive && (strchr (filename, '*') || strchr (filename, '?')))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		char path[256];
 | 
							char path[256];
 | 
				
			||||||
		char wild[256];
 | 
							char wild[256];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		safe_strcpy (wild, file_part (file), sizeof (wild));
 | 
							safe_strcpy (wild, file_part (filename), sizeof (wild));
 | 
				
			||||||
		path_part (file, path, sizeof (path));
 | 
							path_part (filename, path, sizeof (path));
 | 
				
			||||||
		if (path[0] != '/' || path[1] != '\0')
 | 
							if (path[0] != '/' || path[1] != '\0')
 | 
				
			||||||
			path[strlen (path) - 1] = 0;	/* remove trailing slash */
 | 
								path[strlen (path) - 1] = 0;	/* remove trailing slash */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1794,7 +1802,7 @@ dcc_send (struct session *sess, char *to, char *file, int maxcps, int passive)
 | 
				
			||||||
		dccto = to;
 | 
							dccto = to;
 | 
				
			||||||
		dccmaxcps = maxcps;
 | 
							dccmaxcps = maxcps;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		free (file);
 | 
							g_free (filename);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		recursive = TRUE;
 | 
							recursive = TRUE;
 | 
				
			||||||
		for_files (path, wild, dcc_send_wild);
 | 
							for_files (path, wild, dcc_send_wild);
 | 
				
			||||||
| 
						 | 
					@ -1806,91 +1814,123 @@ dcc_send (struct session *sess, char *to, char *file, int maxcps, int passive)
 | 
				
			||||||
	dcc = new_dcc ();
 | 
						dcc = new_dcc ();
 | 
				
			||||||
	if (!dcc)
 | 
						if (!dcc)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		free (file);
 | 
							g_free (filename);
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	dcc->file = file;
 | 
					
 | 
				
			||||||
 | 
						dcc->file = filename;
 | 
				
			||||||
	dcc->maxcps = maxcps;
 | 
						dcc->maxcps = maxcps;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (g_stat (file, &st) != -1)
 | 
						filename_fs = g_filename_from_utf8 (filename, -1, NULL, NULL, NULL);
 | 
				
			||||||
 | 
						if (filename_fs == NULL)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
							PrintTextf(sess, _("Cannot access %s\n"), dcc->file);
 | 
				
			||||||
 | 
							PrintTextf(sess, "%s %d: %s\n", _("Error"), errno, errorstring(errno));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef USE_DCC64
 | 
							dcc_close(dcc, 0, TRUE); /* dcc_close will free dcc->file */
 | 
				
			||||||
		if (sizeof (st.st_size) > 4 && st.st_size > 4294967295U)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			PrintText (sess, "Cannot send files larger than 4 GB.\n");
 | 
					 | 
				
			||||||
			goto xit;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!(*file_part (file)) || S_ISDIR (st.st_mode) || st.st_size < 1)
 | 
							return;
 | 
				
			||||||
		{
 | 
						}
 | 
				
			||||||
			PrintText (sess, "Cannot send directories or empty files.\n");
 | 
					
 | 
				
			||||||
			goto xit;
 | 
						file = g_file_new_for_path (filename_fs);
 | 
				
			||||||
		}
 | 
						if (file == NULL)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
		dcc->starttime = dcc->offertime = time (0);
 | 
							return;
 | 
				
			||||||
		dcc->serv = sess->server;
 | 
						}
 | 
				
			||||||
		dcc->dccstat = STAT_QUEUED;
 | 
					
 | 
				
			||||||
		dcc->size = st.st_size;
 | 
						file_info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SIZE "," G_FILE_ATTRIBUTE_STANDARD_TYPE, G_FILE_QUERY_INFO_NONE, NULL, NULL);
 | 
				
			||||||
		dcc->type = TYPE_SEND;
 | 
					
 | 
				
			||||||
		dcc->fp = g_open (file, OFLAGS | O_RDONLY, 0);
 | 
						g_object_unref (file);
 | 
				
			||||||
		if (dcc->fp != -1)
 | 
					
 | 
				
			||||||
		{
 | 
						if (file_info == NULL)
 | 
				
			||||||
			if (passive || dcc_listen_init (dcc, sess))
 | 
						{
 | 
				
			||||||
			{
 | 
							PrintTextf (sess, _("Cannot access %s\n"), dcc->file);
 | 
				
			||||||
				char havespaces = 0;
 | 
							PrintTextf (sess, "%s %d: %s\n", _("Error"), errno, errorstring (errno));
 | 
				
			||||||
				while (*file)
 | 
					
 | 
				
			||||||
				{
 | 
							dcc_close (dcc, 0, TRUE); /* dcc_close will free dcc->file */
 | 
				
			||||||
					if (*file == ' ')
 | 
					
 | 
				
			||||||
					{
 | 
							return;
 | 
				
			||||||
						if (prefs.hex_dcc_send_fillspaces)
 | 
						}
 | 
				
			||||||
				    		*file = '_';
 | 
					
 | 
				
			||||||
					  	else
 | 
						file_type = g_file_info_get_file_type (file_info);
 | 
				
			||||||
					   	havespaces = 1;
 | 
						file_size = g_file_info_get_size (file_info);
 | 
				
			||||||
					}
 | 
					
 | 
				
			||||||
					file++;
 | 
						g_object_unref (file_info);
 | 
				
			||||||
				}
 | 
					
 | 
				
			||||||
				dcc->nick = strdup (to);
 | 
						if (*file_part (filename) == '\0' || file_type == G_FILE_TYPE_DIRECTORY || file_size <= 0)
 | 
				
			||||||
				if (prefs.hex_gui_autoopen_send)
 | 
						{
 | 
				
			||||||
				{
 | 
							PrintText (sess, "Cannot send directories or empty files.\n");
 | 
				
			||||||
					if (fe_dcc_open_send_win (TRUE))	/* already open? add */
 | 
					
 | 
				
			||||||
						fe_dcc_add (dcc);
 | 
							dcc_close (dcc, 0, TRUE); /* dcc_close will free dcc->file */
 | 
				
			||||||
				} else
 | 
					
 | 
				
			||||||
					fe_dcc_add (dcc);
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
				if (passive)
 | 
					
 | 
				
			||||||
				{
 | 
						dcc->starttime = dcc->offertime = time (0);
 | 
				
			||||||
					dcc->pasvid = new_id();
 | 
						dcc->serv = sess->server;
 | 
				
			||||||
					snprintf (outbuf, sizeof (outbuf), (havespaces) ?
 | 
						dcc->dccstat = STAT_QUEUED;
 | 
				
			||||||
							"DCC SEND \"%s\" 199 0 %" DCC_SFMT " %d" :
 | 
						dcc->size = file_size;
 | 
				
			||||||
							"DCC SEND %s 199 0 %" DCC_SFMT " %d",
 | 
						dcc->type = TYPE_SEND;
 | 
				
			||||||
							file_part (dcc->file),
 | 
						dcc->fp = g_open (filename_fs, OFLAGS | O_RDONLY, 0);
 | 
				
			||||||
							dcc->size, dcc->pasvid);
 | 
					
 | 
				
			||||||
				}
 | 
						g_free (filename_fs);
 | 
				
			||||||
				else
 | 
					
 | 
				
			||||||
				{
 | 
						if (dcc->fp == -1)
 | 
				
			||||||
					snprintf (outbuf, sizeof (outbuf), (havespaces) ?
 | 
						{
 | 
				
			||||||
							"DCC SEND \"%s\" %u %d %"DCC_SFMT :
 | 
							PrintText (sess, "Cannot send directories or empty files.\n");
 | 
				
			||||||
							"DCC SEND %s %u %d %"DCC_SFMT,
 | 
					
 | 
				
			||||||
							file_part (dcc->file), dcc->addr,
 | 
							g_object_unref (file_info);
 | 
				
			||||||
							dcc->port, dcc->size);
 | 
							dcc_close (dcc, 0, TRUE); /* dcc_close will free dcc->file */
 | 
				
			||||||
				}
 | 
						}
 | 
				
			||||||
				sess->server->p_ctcp (sess->server, to, outbuf);
 | 
					
 | 
				
			||||||
 | 
						if (passive || dcc_listen_init (dcc, sess))
 | 
				
			||||||
				EMIT_SIGNAL (XP_TE_DCCOFFER, sess, file_part (dcc->file),
 | 
						{
 | 
				
			||||||
								 to, dcc->file, NULL, 0);
 | 
							char havespaces = 0;
 | 
				
			||||||
			} else
 | 
							while (*filename)
 | 
				
			||||||
			{
 | 
							{
 | 
				
			||||||
				dcc_close (dcc, 0, TRUE);
 | 
								if (*filename == ' ')
 | 
				
			||||||
			}
 | 
								{
 | 
				
			||||||
			return;
 | 
									if (prefs.hex_dcc_send_fillspaces)
 | 
				
			||||||
		}
 | 
									    *filename = '_';
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
 | 
									havespaces = 1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								filename++;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							dcc->nick = strdup (to);
 | 
				
			||||||
 | 
							if (prefs.hex_gui_autoopen_send)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (fe_dcc_open_send_win (TRUE))	/* already open? add */
 | 
				
			||||||
 | 
									fe_dcc_add (dcc);
 | 
				
			||||||
 | 
							} else
 | 
				
			||||||
 | 
								fe_dcc_add (dcc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (passive)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								dcc->pasvid = new_id();
 | 
				
			||||||
 | 
								snprintf (outbuf, sizeof (outbuf), (havespaces) ?
 | 
				
			||||||
 | 
										"DCC SEND \"%s\" 199 0 %" G_GUINT64_FORMAT " %d" :
 | 
				
			||||||
 | 
										"DCC SEND %s 199 0 %" G_GUINT64_FORMAT " %d",
 | 
				
			||||||
 | 
										file_part (dcc->file),
 | 
				
			||||||
 | 
										dcc->size, dcc->pasvid);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								snprintf (outbuf, sizeof (outbuf), (havespaces) ?
 | 
				
			||||||
 | 
										"DCC SEND \"%s\" %u %d %" G_GUINT64_FORMAT :
 | 
				
			||||||
 | 
										"DCC SEND %s %u %d %" G_GUINT64_FORMAT,
 | 
				
			||||||
 | 
										file_part (dcc->file), dcc->addr,
 | 
				
			||||||
 | 
										dcc->port, dcc->size);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							sess->server->p_ctcp (sess->server, to, outbuf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							EMIT_SIGNAL (XP_TE_DCCOFFER, sess, file_part (dcc->file),
 | 
				
			||||||
 | 
												to, dcc->file, NULL, 0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							dcc_close (dcc, 0, TRUE);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	PrintTextf (sess, _("Cannot access %s\n"), dcc->file);
 | 
					 | 
				
			||||||
	PrintTextf (sess, "%s %d: %s\n", _("Error"), errno, errorstring (errno));
 | 
					 | 
				
			||||||
xit:
 | 
					 | 
				
			||||||
	dcc_close (dcc, 0, TRUE);		/* dcc_close will free dcc->file */
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct DCC *
 | 
					static struct DCC *
 | 
				
			||||||
| 
						 | 
					@ -1976,68 +2016,175 @@ dcc_change_nick (struct server *serv, char *oldnick, char *newnick)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* is the destination file the same? new_dcc is not opened yet */
 | 
					/* is the destination file the same? new_dcc is not opened yet */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int
 | 
					static gboolean
 | 
				
			||||||
is_same_file (struct DCC *dcc, struct DCC *new_dcc)
 | 
					is_same_file (struct DCC *dcc, struct DCC *new_dcc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
#ifndef WIN32
 | 
						gboolean result = FALSE;
 | 
				
			||||||
	GStatBuf st_a, st_b;
 | 
						gchar *filename_fs = NULL, *new_filename_fs = NULL;
 | 
				
			||||||
#endif
 | 
						GFile *file = NULL, *new_file = NULL;
 | 
				
			||||||
 | 
						GFileInfo *file_info = NULL, *new_file_info = NULL;
 | 
				
			||||||
 | 
						char *file_id = NULL, *new_file_id = NULL;
 | 
				
			||||||
 | 
						char *filesystem_id = NULL, *new_filesystem_id = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* if it's the same filename, must be same */
 | 
						/* if it's the same filename, must be same */
 | 
				
			||||||
	if (strcmp (dcc->destfile, new_dcc->destfile) == 0)
 | 
						if (strcmp (dcc->destfile, new_dcc->destfile) == 0)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
		return TRUE;
 | 
							return TRUE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* now handle case-insensitive Filesystems: HFS+, FAT */
 | 
						filename_fs = g_filename_from_utf8 (dcc->file, -1, NULL, NULL, NULL);
 | 
				
			||||||
#ifdef WIN32
 | 
						if (filename_fs == NULL)
 | 
				
			||||||
	/* warning no win32 implementation - behaviour may be unreliable */
 | 
						{
 | 
				
			||||||
#else
 | 
							goto exit;
 | 
				
			||||||
	/* this fstat() shouldn't really fail */
 | 
						}
 | 
				
			||||||
	if ((dcc->fp == -1 ? g_stat (dcc->destfile, &st_a) : fstat (dcc->fp, &st_a)) == -1)
 | 
					 | 
				
			||||||
		return FALSE;
 | 
					 | 
				
			||||||
	if (g_stat (new_dcc->destfile, &st_b) == -1)
 | 
					 | 
				
			||||||
		return FALSE;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* same inode, same device, same file! */
 | 
						new_filename_fs = g_filename_from_utf8 (new_dcc->file, -1, NULL, NULL, NULL);
 | 
				
			||||||
	if (st_a.st_ino == st_b.st_ino &&
 | 
						if (new_filename_fs == NULL)
 | 
				
			||||||
		 st_a.st_dev == st_b.st_dev)
 | 
						{
 | 
				
			||||||
		return TRUE;
 | 
							goto exit;
 | 
				
			||||||
#endif
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return FALSE;
 | 
						file = g_file_new_for_path (filename_fs);
 | 
				
			||||||
 | 
						if (file == NULL)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							goto exit;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						new_file = g_file_new_for_path (new_filename_fs);
 | 
				
			||||||
 | 
						if (new_file == NULL)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							goto exit;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						file_info = g_file_query_info (file, G_FILE_ATTRIBUTE_ID_FILE "," G_FILE_ATTRIBUTE_ID_FILESYSTEM, G_FILE_QUERY_INFO_NONE, NULL, NULL);
 | 
				
			||||||
 | 
						if (file_info == NULL)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							goto exit;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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);
 | 
				
			||||||
 | 
						if (file_info == NULL)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							goto exit;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						file_id = g_file_info_get_attribute_as_string (file_info, G_FILE_ATTRIBUTE_ID_FILE);
 | 
				
			||||||
 | 
						new_file_id = g_file_info_get_attribute_as_string (new_file_info, G_FILE_ATTRIBUTE_ID_FILE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						filesystem_id = g_file_info_get_attribute_as_string (file_info, G_FILE_ATTRIBUTE_ID_FILE);
 | 
				
			||||||
 | 
						new_filesystem_id = g_file_info_get_attribute_as_string (new_file_info, G_FILE_ATTRIBUTE_ID_FILE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							result = TRUE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exit:
 | 
				
			||||||
 | 
						if (filename_fs != NULL)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							g_free (filename_fs);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (new_filename_fs != NULL)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							g_free (new_filename_fs);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (file != NULL)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							g_object_unref (file);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (new_file != NULL)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							g_object_unref (new_file);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (file_info != NULL)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							g_object_unref (file_info);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (new_file_info != NULL)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							g_object_unref (new_file_info);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (file_id != NULL)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							g_free (file_id);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (new_file_id != NULL)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							g_free (new_file_id);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (filesystem_id != NULL)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							g_free(filesystem_id);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (new_filesystem_id != NULL)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							g_free(new_filesystem_id);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int
 | 
					static void
 | 
				
			||||||
is_resumable (struct DCC *dcc)
 | 
					update_is_resumable (struct DCC *dcc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						gchar *filename_fs = g_filename_from_utf8 (dcc->destfile, -1, NULL, NULL, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dcc->resumable = 0;
 | 
						dcc->resumable = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Check the file size */
 | 
						/* Check the file size */
 | 
				
			||||||
	if (g_access (dcc->destfile, W_OK) == 0)
 | 
						if (filename_fs != NULL && g_access(filename_fs, W_OK) == 0)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		GStatBuf st;
 | 
							GFile *file = g_file_new_for_path (filename_fs);
 | 
				
			||||||
 | 
							if (file != NULL)
 | 
				
			||||||
		if (g_stat (dcc->destfile, &st) != -1)
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (st.st_size < dcc->size)
 | 
								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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (file_info != NULL)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				dcc->resumable = st.st_size;
 | 
									goffset file_size_offset = g_file_info_get_size (file_info);
 | 
				
			||||||
				dcc->pos = st.st_size;
 | 
									guint64 file_size = (file_size_offset >= 0) ? (guint64) file_size_offset : 0;
 | 
				
			||||||
 | 
									if (file_size < dcc->size)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										dcc->resumable = file_size;
 | 
				
			||||||
 | 
										dcc->pos = file_size;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										dcc->resume_error = 2;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									g_object_unref (file_info);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
				dcc->resume_error = 2;
 | 
								{
 | 
				
			||||||
		} else
 | 
									dcc->resume_errno = errno;
 | 
				
			||||||
 | 
									dcc->resume_error = 1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								g_object_unref(file);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			dcc->resume_errno = errno;
 | 
								dcc->resume_errno = errno;
 | 
				
			||||||
			dcc->resume_error = 1;
 | 
								dcc->resume_error = 1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		dcc->resume_errno = errno;
 | 
							dcc->resume_errno = errno;
 | 
				
			||||||
		dcc->resume_error = 1;
 | 
							dcc->resume_error = 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Now verify that this DCC is not already in progress from someone else */
 | 
						/* Now verify that this DCC is not already in progress from someone else */
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (dcc->resumable)
 | 
						if (dcc->resumable)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		GSList *list = dcc_list;
 | 
							GSList *list = dcc_list;
 | 
				
			||||||
| 
						 | 
					@ -2059,8 +2206,6 @@ is_resumable (struct DCC *dcc)
 | 
				
			||||||
			list = list->next;
 | 
								list = list->next;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return dcc->resumable;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
| 
						 | 
					@ -2100,7 +2245,7 @@ dcc_get_with_destfile (struct DCC *dcc, char *file)
 | 
				
			||||||
	dcc->destfile = g_strdup (file);	/* utf-8 */
 | 
						dcc->destfile = g_strdup (file);	/* utf-8 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* since destfile changed, must check resumability again */
 | 
						/* since destfile changed, must check resumability again */
 | 
				
			||||||
	is_resumable (dcc);
 | 
						update_is_resumable (dcc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dcc_get (dcc);
 | 
						dcc_get (dcc);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -2133,14 +2278,13 @@ dcc_get_nick (struct session *sess, char *nick)
 | 
				
			||||||
static struct DCC *
 | 
					static struct DCC *
 | 
				
			||||||
new_dcc (void)
 | 
					new_dcc (void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct DCC *dcc = malloc (sizeof (struct DCC));
 | 
						struct DCC *dcc = calloc (1, sizeof (struct DCC));
 | 
				
			||||||
	if (!dcc)
 | 
						if (!dcc)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	memset (dcc, 0, sizeof (struct DCC));
 | 
					 | 
				
			||||||
	dcc->sok = -1;
 | 
						dcc->sok = -1;
 | 
				
			||||||
	dcc->fp = -1;
 | 
						dcc->fp = -1;
 | 
				
			||||||
	dcc_list = g_slist_prepend (dcc_list, dcc);
 | 
						dcc_list = g_slist_prepend (dcc_list, dcc);
 | 
				
			||||||
	return (dcc);
 | 
						return dcc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
| 
						 | 
					@ -2231,8 +2375,8 @@ dcc_resume (struct DCC *dcc)
 | 
				
			||||||
		dcc->resume_sent = 1;
 | 
							dcc->resume_sent = 1;
 | 
				
			||||||
		/* filename contains spaces? Quote them! */
 | 
							/* filename contains spaces? Quote them! */
 | 
				
			||||||
		snprintf (tbuf, sizeof (tbuf) - 10, strchr (dcc->file, ' ') ?
 | 
							snprintf (tbuf, sizeof (tbuf) - 10, strchr (dcc->file, ' ') ?
 | 
				
			||||||
					  "DCC RESUME \"%s\" %d %"DCC_SFMT :
 | 
										  "DCC RESUME \"%s\" %d %" G_GUINT64_FORMAT :
 | 
				
			||||||
					  "DCC RESUME %s %d %"DCC_SFMT,
 | 
										  "DCC RESUME %s %d %" G_GUINT64_FORMAT,
 | 
				
			||||||
					  dcc->file, dcc->port, dcc->resumable);
 | 
										  dcc->file, dcc->port, dcc->resumable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (dcc->pasvid)
 | 
							if (dcc->pasvid)
 | 
				
			||||||
| 
						 | 
					@ -2316,7 +2460,7 @@ dcc_add_chat (session *sess, char *nick, int port, guint32 addr, int pasvid)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct DCC *
 | 
					static struct DCC *
 | 
				
			||||||
dcc_add_file (session *sess, char *file, DCC_SIZE size, int port, char *nick, guint32 addr, int pasvid)
 | 
					dcc_add_file (session *sess, char *file, guint64 size, int port, char *nick, guint32 addr, int pasvid)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct DCC *dcc;
 | 
						struct DCC *dcc;
 | 
				
			||||||
	char tbuf[512];
 | 
						char tbuf[512];
 | 
				
			||||||
| 
						 | 
					@ -2324,7 +2468,7 @@ dcc_add_file (session *sess, char *file, DCC_SIZE size, int port, char *nick, gu
 | 
				
			||||||
	dcc = new_dcc ();
 | 
						dcc = new_dcc ();
 | 
				
			||||||
	if (dcc)
 | 
						if (dcc)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		dcc->file = strdup (file);
 | 
							dcc->file = g_strdup (file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dcc->destfile = g_malloc (strlen (prefs.hex_dcc_dir) + strlen (nick) +
 | 
							dcc->destfile = g_malloc (strlen (prefs.hex_dcc_dir) + strlen (nick) +
 | 
				
			||||||
										  strlen (file) + 4);
 | 
															  strlen (file) + 4);
 | 
				
			||||||
| 
						 | 
					@ -2362,7 +2506,7 @@ dcc_add_file (session *sess, char *file, DCC_SIZE size, int port, char *nick, gu
 | 
				
			||||||
		dcc->nick = strdup (nick);
 | 
							dcc->nick = strdup (nick);
 | 
				
			||||||
		dcc->maxcps = prefs.hex_dcc_max_get_cps;
 | 
							dcc->maxcps = prefs.hex_dcc_max_get_cps;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		is_resumable (dcc);
 | 
							update_is_resumable (dcc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (prefs.hex_dcc_auto_recv == 1)
 | 
							if (prefs.hex_dcc_auto_recv == 1)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
| 
						 | 
					@ -2380,7 +2524,7 @@ dcc_add_file (session *sess, char *file, DCC_SIZE size, int port, char *nick, gu
 | 
				
			||||||
		} else
 | 
							} else
 | 
				
			||||||
			fe_dcc_add (dcc);
 | 
								fe_dcc_add (dcc);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	sprintf (tbuf, "%"DCC_SFMT, size);
 | 
						sprintf (tbuf, "%" G_GUINT64_FORMAT, size);
 | 
				
			||||||
	snprintf (tbuf + 24, 300, "%s:%d", net_ip (addr), port);
 | 
						snprintf (tbuf + 24, 300, "%s:%d", net_ip (addr), port);
 | 
				
			||||||
	EMIT_SIGNAL (XP_TE_DCCSENDOFFER, sess->server->front_session, nick,
 | 
						EMIT_SIGNAL (XP_TE_DCCSENDOFFER, sess->server->front_session, nick,
 | 
				
			||||||
					 file, tbuf, tbuf + 24, 0);
 | 
										 file, tbuf, tbuf + 24, 0);
 | 
				
			||||||
| 
						 | 
					@ -2397,7 +2541,7 @@ handle_dcc (struct session *sess, char *nick, char *word[], char *word_eol[],
 | 
				
			||||||
	char *type = word[5];
 | 
						char *type = word[5];
 | 
				
			||||||
	int port, pasvid = 0;
 | 
						int port, pasvid = 0;
 | 
				
			||||||
	guint32 addr;
 | 
						guint32 addr;
 | 
				
			||||||
	DCC_SIZE size;
 | 
						guint64 size;
 | 
				
			||||||
	int psend = 0;
 | 
						int psend = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!g_ascii_strcasecmp (type, "CHAT"))
 | 
						if (!g_ascii_strcasecmp (type, "CHAT"))
 | 
				
			||||||
| 
						 | 
					@ -2463,7 +2607,7 @@ handle_dcc (struct session *sess, char *nick, char *word[], char *word_eol[],
 | 
				
			||||||
			dcc = find_dcc (nick, word[6], TYPE_SEND);
 | 
								dcc = find_dcc (nick, word[6], TYPE_SEND);
 | 
				
			||||||
		if (dcc)
 | 
							if (dcc)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			size = BIG_STR_TO_INT (word[8]);
 | 
								size = g_ascii_strtoull (word[8], NULL, 10);
 | 
				
			||||||
			dcc->resumable = size;
 | 
								dcc->resumable = size;
 | 
				
			||||||
			if (dcc->resumable < dcc->size)
 | 
								if (dcc->resumable < dcc->size)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
| 
						 | 
					@ -2474,18 +2618,18 @@ handle_dcc (struct session *sess, char *nick, char *word[], char *word_eol[],
 | 
				
			||||||
				/* Checking if dcc is passive and if filename contains spaces */
 | 
									/* Checking if dcc is passive and if filename contains spaces */
 | 
				
			||||||
				if (dcc->pasvid)
 | 
									if (dcc->pasvid)
 | 
				
			||||||
					snprintf (tbuf, sizeof (tbuf), strchr (file_part (dcc->file), ' ') ?
 | 
										snprintf (tbuf, sizeof (tbuf), strchr (file_part (dcc->file), ' ') ?
 | 
				
			||||||
							"DCC ACCEPT \"%s\" %d %"DCC_SFMT" %d" :
 | 
												"DCC ACCEPT \"%s\" %d %" G_GUINT64_FORMAT " %d" :
 | 
				
			||||||
							"DCC ACCEPT %s %d %"DCC_SFMT" %d",
 | 
												"DCC ACCEPT %s %d %" G_GUINT64_FORMAT " %d",
 | 
				
			||||||
							file_part (dcc->file), port, dcc->resumable, dcc->pasvid);
 | 
												file_part (dcc->file), port, dcc->resumable, dcc->pasvid);
 | 
				
			||||||
				else
 | 
									else
 | 
				
			||||||
					snprintf (tbuf, sizeof (tbuf), strchr (file_part (dcc->file), ' ') ?
 | 
										snprintf (tbuf, sizeof (tbuf), strchr (file_part (dcc->file), ' ') ?
 | 
				
			||||||
							"DCC ACCEPT \"%s\" %d %"DCC_SFMT :
 | 
												"DCC ACCEPT \"%s\" %d %" G_GUINT64_FORMAT :
 | 
				
			||||||
							"DCC ACCEPT %s %d %"DCC_SFMT,
 | 
												"DCC ACCEPT %s %d %" G_GUINT64_FORMAT,
 | 
				
			||||||
							file_part (dcc->file), port, dcc->resumable);
 | 
												file_part (dcc->file), port, dcc->resumable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				dcc->serv->p_ctcp (dcc->serv, dcc->nick, tbuf);
 | 
									dcc->serv->p_ctcp (dcc->serv, dcc->nick, tbuf);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			sprintf (tbuf, "%"DCC_SFMT, dcc->pos);
 | 
								sprintf (tbuf, "%" G_GUINT64_FORMAT, dcc->pos);
 | 
				
			||||||
			EMIT_SIGNAL_TIMESTAMP (XP_TE_DCCRESUMEREQUEST, sess, nick,
 | 
								EMIT_SIGNAL_TIMESTAMP (XP_TE_DCCRESUMEREQUEST, sess, nick,
 | 
				
			||||||
										  file_part (dcc->file), tbuf, NULL, 0,
 | 
															  file_part (dcc->file), tbuf, NULL, 0,
 | 
				
			||||||
										  tags_data->timestamp);
 | 
															  tags_data->timestamp);
 | 
				
			||||||
| 
						 | 
					@ -2508,7 +2652,7 @@ handle_dcc (struct session *sess, char *nick, char *word[], char *word_eol[],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		port = atoi (word[8]);
 | 
							port = atoi (word[8]);
 | 
				
			||||||
		addr = strtoul (word[7], NULL, 10);
 | 
							addr = strtoul (word[7], NULL, 10);
 | 
				
			||||||
		size = BIG_STR_TO_INT (word[9]);
 | 
							size = g_ascii_strtoull (word[9], NULL, 10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (port == 0) /* Passive dcc requested */
 | 
							if (port == 0) /* Passive dcc requested */
 | 
				
			||||||
			pasvid = atoi (word[10]);
 | 
								pasvid = atoi (word[10]);
 | 
				
			||||||
| 
						 | 
					@ -2576,7 +2720,7 @@ dcc_show_list (struct session *sess)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		dcc = (struct DCC *) list->data;
 | 
							dcc = (struct DCC *) list->data;
 | 
				
			||||||
		i++;
 | 
							i++;
 | 
				
			||||||
		PrintTextf (sess, " %s  %-10.10s %-7.7s %-7"DCC_SFMT" %-7"DCC_SFMT" %s\n",
 | 
							PrintTextf (sess, " %s  %-10.10s %-7.7s %-7" G_GUINT64_FORMAT " %-7" G_GUINT64_FORMAT " %s\n",
 | 
				
			||||||
					 dcctypes[dcc->type], dcc->nick,
 | 
										 dcctypes[dcc->type], dcc->nick,
 | 
				
			||||||
					 _(dccstat[dcc->dccstat].name), dcc->size, dcc->pos,
 | 
										 _(dccstat[dcc->dccstat].name), dcc->size, dcc->pos,
 | 
				
			||||||
					 file_part (dcc->file));
 | 
										 file_part (dcc->file));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,17 +39,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CPS_AVG_WINDOW 10
 | 
					#define CPS_AVG_WINDOW 10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* can we do 64-bit dcc? */
 | 
					 | 
				
			||||||
#if defined(G_GINT64_FORMAT) && defined(HAVE_STRTOULL)
 | 
					 | 
				
			||||||
#define USE_DCC64
 | 
					 | 
				
			||||||
/* we really get only 63 bits, since st_size is signed */
 | 
					 | 
				
			||||||
#define DCC_SIZE gint64
 | 
					 | 
				
			||||||
#define DCC_SFMT G_GINT64_FORMAT
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
#define DCC_SIZE unsigned int
 | 
					 | 
				
			||||||
#define DCC_SFMT "u"
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct DCC
 | 
					struct DCC
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct server *serv;
 | 
						struct server *serv;
 | 
				
			||||||
| 
						 | 
					@ -62,21 +51,21 @@ struct DCC
 | 
				
			||||||
	int wiotag;						/* writing/sending io tag */
 | 
						int wiotag;						/* writing/sending io tag */
 | 
				
			||||||
	int port;
 | 
						int port;
 | 
				
			||||||
	int pasvid;						/* mIRC's passive DCC id */
 | 
						int pasvid;						/* mIRC's passive DCC id */
 | 
				
			||||||
	int cps;
 | 
						gint64 cps;
 | 
				
			||||||
	int resume_error;
 | 
						int resume_error;
 | 
				
			||||||
	int resume_errno;
 | 
						int resume_errno;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	GTimeVal lastcpstv, firstcpstv;
 | 
						GTimeVal lastcpstv, firstcpstv;
 | 
				
			||||||
	DCC_SIZE lastcpspos;
 | 
						goffset lastcpspos;
 | 
				
			||||||
	int maxcps;
 | 
						gint64 maxcps;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	unsigned char ack_buf[4];	/* buffer for reading 4-byte ack */
 | 
						unsigned char ack_buf[4];	/* buffer for reading 4-byte ack */
 | 
				
			||||||
	int ack_pos;
 | 
						int ack_pos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	DCC_SIZE size;
 | 
						guint64 size;
 | 
				
			||||||
	DCC_SIZE resumable;
 | 
						guint64 resumable;
 | 
				
			||||||
	DCC_SIZE ack;
 | 
						guint64 ack;
 | 
				
			||||||
	DCC_SIZE pos;
 | 
						guint64 pos;
 | 
				
			||||||
	time_t starttime;
 | 
						time_t starttime;
 | 
				
			||||||
	time_t offertime;
 | 
						time_t offertime;
 | 
				
			||||||
	time_t lasttime;
 | 
						time_t lasttime;
 | 
				
			||||||
| 
						 | 
					@ -125,7 +114,7 @@ void dcc_check_timeouts (void);
 | 
				
			||||||
void dcc_change_nick (server *serv, char *oldnick, char *newnick);
 | 
					void dcc_change_nick (server *serv, char *oldnick, char *newnick);
 | 
				
			||||||
void dcc_notify_kill (struct server *serv);
 | 
					void dcc_notify_kill (struct server *serv);
 | 
				
			||||||
struct DCC *dcc_write_chat (char *nick, char *text);
 | 
					struct DCC *dcc_write_chat (char *nick, char *text);
 | 
				
			||||||
void dcc_send (struct session *sess, char *to, char *file, int maxcps, int passive);
 | 
					void dcc_send (struct session *sess, char *to, char *file, gint64 maxcps, int passive);
 | 
				
			||||||
struct DCC *find_dcc (char *nick, char *file, int type);
 | 
					struct DCC *find_dcc (char *nick, char *file, int type);
 | 
				
			||||||
void dcc_get_nick (struct session *sess, char *nick);
 | 
					void dcc_get_nick (struct session *sess, char *nick);
 | 
				
			||||||
void dcc_chat (session *sess, char *nick, int passive);
 | 
					void dcc_chat (session *sess, char *nick, int passive);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1531,7 +1531,14 @@ hexchat_list_int (hexchat_plugin *ph, hexchat_list *xlist, const char *name)
 | 
				
			||||||
		case 0x34207553: /* address32 */
 | 
							case 0x34207553: /* address32 */
 | 
				
			||||||
			return ((struct DCC *)data)->addr;
 | 
								return ((struct DCC *)data)->addr;
 | 
				
			||||||
		case 0x181a6: /* cps */
 | 
							case 0x181a6: /* cps */
 | 
				
			||||||
			return ((struct DCC *)data)->cps;
 | 
							{
 | 
				
			||||||
 | 
								gint64 cps = ((struct DCC *)data)->cps;
 | 
				
			||||||
 | 
								if (cps <= INT_MAX)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									return (int) cps;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return INT_MAX;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		case 0x349881: /* port */
 | 
							case 0x349881: /* port */
 | 
				
			||||||
			return ((struct DCC *)data)->port;
 | 
								return ((struct DCC *)data)->port;
 | 
				
			||||||
		case 0x1b254: /* pos */
 | 
							case 0x1b254: /* pos */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -88,7 +88,7 @@ struct my_dcc_send
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct session *sess;
 | 
						struct session *sess;
 | 
				
			||||||
	char *nick;
 | 
						char *nick;
 | 
				
			||||||
	int maxcps;
 | 
						gint64 maxcps;
 | 
				
			||||||
	int passive;
 | 
						int passive;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -105,7 +105,7 @@ static short view_mode;	/* 1=download 2=upload 3=both */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
proper_unit (DCC_SIZE size, char *buf, int buf_len)
 | 
					proper_unit (guint64 size, char *buf, size_t buf_len)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	gchar *formatted_str;
 | 
						gchar *formatted_str;
 | 
				
			||||||
	GFormatSizeFlags format_flags = G_FORMAT_SIZE_DEFAULT;
 | 
						GFormatSizeFlags format_flags = G_FORMAT_SIZE_DEFAULT;
 | 
				
			||||||
| 
						 | 
					@ -117,7 +117,7 @@ proper_unit (DCC_SIZE size, char *buf, int buf_len)
 | 
				
			||||||
		format_flags = G_FORMAT_SIZE_IEC_UNITS;
 | 
							format_flags = G_FORMAT_SIZE_IEC_UNITS;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	formatted_str = g_format_size_full ((guint64)size, format_flags);
 | 
						formatted_str = g_format_size_full (size, format_flags);
 | 
				
			||||||
	g_strlcpy (buf, formatted_str, buf_len);
 | 
						g_strlcpy (buf, formatted_str, buf_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	g_free (formatted_str);
 | 
						g_free (formatted_str);
 | 
				
			||||||
| 
						 | 
					@ -155,20 +155,20 @@ static void
 | 
				
			||||||
dcc_prepare_row_chat (struct DCC *dcc, GtkListStore *store, GtkTreeIter *iter,
 | 
					dcc_prepare_row_chat (struct DCC *dcc, GtkListStore *store, GtkTreeIter *iter,
 | 
				
			||||||
							 gboolean update_only)
 | 
												 gboolean update_only)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	static char pos[16], siz[16];
 | 
						static char pos[16], size[16];
 | 
				
			||||||
	char *date;
 | 
						char *date;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	date = ctime (&dcc->starttime);
 | 
						date = ctime (&dcc->starttime);
 | 
				
			||||||
	date[strlen (date) - 1] = 0;	/* remove the \n */
 | 
						date[strlen (date) - 1] = 0;	/* remove the \n */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	proper_unit (dcc->pos, pos, sizeof (pos));
 | 
						proper_unit (dcc->pos, pos, sizeof (pos));
 | 
				
			||||||
	proper_unit (dcc->size, siz, sizeof (siz));
 | 
						proper_unit (dcc->size, size, sizeof (size));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	gtk_list_store_set (store, iter,
 | 
						gtk_list_store_set (store, iter,
 | 
				
			||||||
							  CCOL_STATUS, _(dccstat[dcc->dccstat].name),
 | 
												  CCOL_STATUS, _(dccstat[dcc->dccstat].name),
 | 
				
			||||||
							  CCOL_NICK, dcc->nick,
 | 
												  CCOL_NICK, dcc->nick,
 | 
				
			||||||
							  CCOL_RECV, pos,
 | 
												  CCOL_RECV, pos,
 | 
				
			||||||
							  CCOL_SENT, siz,
 | 
												  CCOL_SENT, size,
 | 
				
			||||||
							  CCOL_START, date,
 | 
												  CCOL_START, date,
 | 
				
			||||||
							  CCOL_DCC, dcc,
 | 
												  CCOL_DCC, dcc,
 | 
				
			||||||
							  CCOL_COLOR,
 | 
												  CCOL_COLOR,
 | 
				
			||||||
| 
						 | 
					@ -195,7 +195,6 @@ dcc_prepare_row_send (struct DCC *dcc, GtkListStore *store, GtkTreeIter *iter,
 | 
				
			||||||
	proper_unit (dcc->size, size, sizeof (size));
 | 
						proper_unit (dcc->size, size, sizeof (size));
 | 
				
			||||||
	proper_unit (dcc->pos, pos, sizeof (pos));
 | 
						proper_unit (dcc->pos, pos, sizeof (pos));
 | 
				
			||||||
	snprintf (kbs, sizeof (kbs), "%.1f", ((float)dcc->cps) / 1024);
 | 
						snprintf (kbs, sizeof (kbs), "%.1f", ((float)dcc->cps) / 1024);
 | 
				
			||||||
/*	proper_unit (dcc->ack, ack, sizeof (ack));*/
 | 
					 | 
				
			||||||
	snprintf (perc, sizeof (perc), "%.0f%%", per);
 | 
						snprintf (perc, sizeof (perc), "%.0f%%", per);
 | 
				
			||||||
	if (dcc->cps != 0)
 | 
						if (dcc->cps != 0)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue