diff options
Diffstat (limited to 'src/common/dcc.c')
-rw-r--r-- | src/common/dcc.c | 594 |
1 files changed, 337 insertions, 257 deletions
diff --git a/src/common/dcc.c b/src/common/dcc.c index 169a0f76..881bcf78 100644 --- a/src/common/dcc.c +++ b/src/common/dcc.c @@ -23,8 +23,9 @@ * 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 + #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -57,13 +58,9 @@ #include "url.h" #include "hexchatc.h" -#ifdef USE_DCC64 -#define BIG_STR_TO_INT(x) strtoull(x,NULL,10) +/* Setting _FILE_OFFSET_BITS to 64 doesn't change lseek to use off64_t on Windows, so override lseek to the version that does */ #ifdef WIN32 -#define stat _stat64 -#endif -#else -#define BIG_STR_TO_INT(x) strtoul(x,NULL,10) +#define lseek _lseeki64 #endif static char *dcctypes[] = { "SEND", "RECV", "CHAT", "CHAT" }; @@ -78,7 +75,7 @@ struct dccstat_info dccstat[] = { }; 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 void dcc_close (struct DCC *dcc, int dccstat, int destroy); @@ -127,11 +124,12 @@ static void dcc_calc_cps (struct DCC *dcc) { GTimeVal now; - int oldcps; + gint64 oldcps; double timediff, startdiff; int glob_throttle_bit, wasthrottled; - int *cpssum, glob_limit; - DCC_SIZE pos, posdiff; + gint64 *cpssum; + int glob_limit; + goffset pos, posdiff; g_get_current_time (&now); @@ -169,8 +167,7 @@ dcc_calc_cps (struct DCC *dcc) posdiff = pos - dcc->lastcpspos; oldcps = dcc->cps; - dcc->cps = ((double) posdiff / timediff) * (timediff / startdiff) + - (double) dcc->cps * (1.0 - (timediff / startdiff)); + dcc->cps = (gint64) ((posdiff / timediff) * (timediff / startdiff) + dcc->cps * (1.0 - (timediff / startdiff))); *cpssum += dcc->cps - oldcps; } @@ -312,7 +309,7 @@ dcc_lookup_proxy (char *host, struct sockaddr_in *addr) memcpy (&addr->sin_addr, &cache_addr, 4); return TRUE; } - free (cache_host); + g_free (cache_host); cache_host = NULL; } @@ -321,7 +318,7 @@ dcc_lookup_proxy (char *host, struct sockaddr_in *addr) { memcpy (&addr->sin_addr, h->h_addr, 4); memcpy (&cache_addr, h->h_addr, 4); - cache_host = strdup (host); + cache_host = g_strdup (host); /* cppcheck-suppress memleak */ return TRUE; } @@ -409,7 +406,7 @@ dcc_close (struct DCC *dcc, int dccstat, int destroy) dcc->dccstat = dccstat; if (dcc->dccchat) { - free (dcc->dccchat); + g_free (dcc->dccchat); dcc->dccchat = NULL; } @@ -417,14 +414,11 @@ dcc_close (struct DCC *dcc, int dccstat, int destroy) { dcc_list = g_slist_remove (dcc_list, dcc); fe_dcc_remove (dcc); - if (dcc->proxy) - free (dcc->proxy); - if (dcc->file) - free (dcc->file); - if (dcc->destfile) - g_free (dcc->destfile); - free (dcc->nick); - free (dcc); + g_free (dcc->proxy); + g_free (dcc->file); + g_free (dcc->destfile); + g_free (dcc->nick); + g_free (dcc); return; } @@ -493,14 +487,13 @@ dcc_write_chat (char *nick, char *text) if (dcc && dcc->dccstat == STAT_ACTIVE) { len = strlen (text); - tcp_send_real (NULL, dcc->sok, dcc->serv->encoding, dcc->serv->using_irc, - text, len); + tcp_send_real (NULL, dcc->sok, dcc->serv->write_converter, text, len); send (dcc->sok, "\n", 1, 0); dcc->size += len; fe_dcc_update (dcc); return dcc; } - return 0; + return NULL; } /* returns: 0 - ok @@ -512,36 +505,11 @@ dcc_chat_line (struct DCC *dcc, char *line) session *sess; char *word[PDIWORDS]; char *po; - char *utf; - char *conv; int ret, i; - int len; - gsize utf_len; char portbuf[32]; message_tags_data no_tags = MESSAGE_TAGS_DATA_INIT; - len = strlen (line); - if (dcc->serv->using_cp1255) - len++; /* include the NUL terminator */ - - if (dcc->serv->using_irc) /* using "IRC" encoding (CP1252/UTF-8 hybrid) */ - utf = NULL; - else if (dcc->serv->encoding == NULL) /* system */ - utf = g_locale_to_utf8 (line, len, NULL, &utf_len, NULL); - else - utf = g_convert (line, len, "UTF-8", dcc->serv->encoding, 0, &utf_len, 0); - - if (utf) - { - line = utf; - len = utf_len; - } - - if (dcc->serv->using_cp1255 && len > 0) - len--; - - /* we really need valid UTF-8 now */ - conv = text_validate (&line, &len); + line = text_convert_invalid (line, -1, dcc->serv->read_converter, unicode_fallback_string, NULL); sess = find_dialog (dcc->serv, dcc->nick); if (!sess) @@ -562,24 +530,18 @@ dcc_chat_line (struct DCC *dcc, char *line) /* did the plugin close it? */ if (!g_slist_find (dcc_list, dcc)) { - if (utf) - g_free (utf); - if (conv) - g_free (conv); + g_free (line); return 1; } /* did the plugin eat the event? */ if (ret) { - if (utf) - g_free (utf); - if (conv) - g_free (conv); + g_free (line); return 0; } - url_check_line (line, len); + url_check_line (line); if (line[0] == 1 && !g_ascii_strncasecmp (line + 1, "ACTION", 6)) { @@ -592,10 +554,7 @@ dcc_chat_line (struct DCC *dcc, char *line) { inbound_privmsg (dcc->serv, dcc->nick, "", line, FALSE, &no_tags); } - if (utf) - g_free (utf); - if (conv) - g_free (conv); + g_free (line); return 0; } @@ -700,20 +659,26 @@ dcc_read (GIOChannel *source, GIOCondition condition, struct DCC *dcc) 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->ack = dcc->resumable; - } else + } + else { + gchar *filename_fs; + if (g_access (dcc->destfile, F_OK) == 0) { n = 0; do { n++; - snprintf (buf, sizeof (buf), "%s.%d", dcc->destfile, n); + g_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; dcc->destfile = g_strdup (buf); @@ -722,9 +687,10 @@ dcc_read (GIOChannel *source, GIOCondition condition, struct DCC *dcc) old, dcc->destfile, NULL, NULL, 0); g_free (old); } - dcc->fp = - g_open (dcc->destfile, OFLAGS | O_TRUNC | O_WRONLY | O_CREAT, - prefs.hex_dcc_permissions); + + filename_fs = g_filename_from_utf8 (dcc->destfile, -1, NULL, NULL, NULL); + 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) @@ -792,7 +758,7 @@ dcc_read (GIOChannel *source, GIOCondition condition, struct DCC *dcc) 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 */ /* cppcheck-suppress deallocuse */ - sprintf (buf, "%d", dcc->cps); + sprintf (buf, "%" G_GINT64_FORMAT, dcc->cps); EMIT_SIGNAL (XP_TE_DCCRECVCOMP, dcc->serv->front_session, dcc->file, dcc->destfile, dcc->nick, buf, 0); return TRUE; @@ -870,7 +836,7 @@ dcc_connect_finished (GIOChannel *source, GIOCondition condition, struct DCC *dc return TRUE; dcc->dccstat = STAT_ACTIVE; - snprintf (host, sizeof host, "%s:%d", net_ip (dcc->addr), dcc->port); + g_snprintf (host, sizeof host, "%s:%d", net_ip (dcc->addr), dcc->port); switch (dcc->type) { @@ -893,8 +859,7 @@ dcc_connect_finished (GIOChannel *source, GIOCondition condition, struct DCC *dc dcc_open_query (dcc->serv, dcc->nick); case TYPE_CHATRECV: /* normal chat */ dcc->iotag = fe_input_add (dcc->sok, FIA_READ|FIA_EX, dcc_read_chat, dcc); - dcc->dccchat = malloc (sizeof (struct dcc_chat)); - dcc->dccchat->pos = 0; + dcc->dccchat = g_new0 (struct dcc_chat, 1); EMIT_SIGNAL (XP_TE_DCCCONCHAT, dcc->serv->front_session, dcc->nick, host, NULL, NULL, 0); break; @@ -990,7 +955,7 @@ dcc_wingate_proxy_traverse (GIOChannel *source, GIOCondition condition, struct D struct proxy_state *proxy = dcc->proxy; if (proxy->phase == 0) { - proxy->buffersize = snprintf ((char*) proxy->buffer, MAX_PROXY_BUFFER, + proxy->buffersize = g_snprintf ((char*) proxy->buffer, MAX_PROXY_BUFFER, "%s %d\r\n", net_ip(dcc->addr), dcc->port); proxy->bufferused = 0; @@ -1288,16 +1253,16 @@ dcc_http_proxy_traverse (GIOChannel *source, GIOCondition condition, struct DCC char auth_data2[68]; int n, n2; - n = snprintf (buf, sizeof (buf), "CONNECT %s:%d HTTP/1.0\r\n", + n = g_snprintf (buf, sizeof (buf), "CONNECT %s:%d HTTP/1.0\r\n", net_ip(dcc->addr), dcc->port); if (prefs.hex_net_proxy_auth) { - n2 = snprintf (auth_data2, sizeof (auth_data2), "%s:%s", + n2 = g_snprintf (auth_data2, sizeof (auth_data2), "%s:%s", prefs.hex_net_proxy_user, prefs.hex_net_proxy_pass); base64_encode (auth_data, auth_data2, n2); - n += snprintf (buf+n, sizeof (buf)-n, "Proxy-Authorization: Basic %s\r\n", auth_data); + n += g_snprintf (buf+n, sizeof (buf)-n, "Proxy-Authorization: Basic %s\r\n", auth_data); } - n += snprintf (buf+n, sizeof (buf)-n, "\r\n"); + n += g_snprintf (buf+n, sizeof (buf)-n, "\r\n"); proxy->buffersize = n; proxy->bufferused = 0; memcpy (proxy->buffer, buf, proxy->buffersize); @@ -1373,14 +1338,7 @@ dcc_proxy_connect (GIOChannel *source, GIOCondition condition, struct DCC *dcc) if (!dcc_did_connect (source, condition, dcc)) return TRUE; - dcc->proxy = malloc (sizeof (struct proxy_state)); - if (!dcc->proxy) - { - dcc->dccstat = STAT_FAILED; - fe_dcc_update (dcc); - return TRUE; - } - memset (dcc->proxy, 0, sizeof (struct proxy_state)); + dcc->proxy = g_new0 (struct proxy_state, 1); switch (prefs.hex_net_proxy_type) { @@ -1415,12 +1373,12 @@ dcc_connect (struct DCC *dcc) } /* possible problems with filenames containing spaces? */ if (dcc->type == TYPE_RECV) - snprintf (tbuf, sizeof (tbuf), strchr (dcc->file, ' ') ? - "DCC SEND \"%s\" %u %d %"DCC_SFMT" %d" : - "DCC SEND %s %u %d %"DCC_SFMT" %d", dcc->file, + g_snprintf (tbuf, sizeof (tbuf), strchr (dcc->file, ' ') ? + "DCC SEND \"%s\" %u %d %" G_GUINT64_FORMAT " %d" : + "DCC SEND %s %u %d %" G_GUINT64_FORMAT " %d", dcc->file, dcc->addr, dcc->port, dcc->size, dcc->pasvid); else - snprintf (tbuf, sizeof (tbuf), "DCC CHAT chat %u %d %d", + g_snprintf (tbuf, sizeof (tbuf), "DCC CHAT chat %u %d %d", dcc->addr, dcc->port, dcc->pasvid); dcc->serv->p_ctcp (dcc->serv, dcc->nick, tbuf); } @@ -1463,15 +1421,13 @@ dcc_send_data (GIOChannel *source, GIOCondition condition, struct DCC *dcc) if (!dcc->fastsend) { - if (dcc->ack < dcc->pos) + if (dcc->ack < (dcc->pos & 0xFFFFFFFF)) return TRUE; } else if (!dcc->wiotag) dcc->wiotag = fe_input_add (sok, FIA_WRITE, dcc_send_data, dcc); - buf = malloc (prefs.hex_dcc_blocksize); - if (!buf) - return TRUE; + buf = g_malloc (prefs.hex_dcc_blocksize); lseek (dcc->fp, dcc->pos, SEEK_SET); len = read (dcc->fp, buf, prefs.hex_dcc_blocksize); @@ -1482,7 +1438,7 @@ dcc_send_data (GIOChannel *source, GIOCondition condition, struct DCC *dcc) if (sent < 0 && !(would_block ())) { abortit: - free (buf); + g_free (buf); EMIT_SIGNAL (XP_TE_DCCSENDFAIL, dcc->serv->front_session, file_part (dcc->file), dcc->nick, errorstring (sock_error ()), NULL, 0); @@ -1506,7 +1462,7 @@ abortit: } } - free (buf); + g_free (buf); return TRUE; } @@ -1538,7 +1494,7 @@ dcc_handle_new_ack (struct DCC *dcc) 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 */ /* cppcheck-suppress deallocuse */ - sprintf (buf, "%d", dcc->cps); + sprintf (buf, "%" G_GINT64_FORMAT, dcc->cps); EMIT_SIGNAL (XP_TE_DCCSENDCOMP, dcc->serv->front_session, file_part (dcc->file), dcc->nick, buf, NULL, 0); done = TRUE; @@ -1548,12 +1504,10 @@ dcc_handle_new_ack (struct DCC *dcc) dcc_send_data (NULL, 0, (gpointer)dcc); } -#ifdef USE_DCC64 /* take the top 32 of "bytes send" and bottom 32 of "ack" */ dcc->ack = (dcc->pos & G_GINT64_CONSTANT (0xffffffff00000000)) | (dcc->ack & 0xffffffff); /* dcc->ack is only used for CPS and PERCENTAGE calcs from now on... */ -#endif return done; } @@ -1622,7 +1576,7 @@ dcc_accept (GIOChannel *source, GIOCondition condition, struct DCC *dcc) dcc->lasttime = dcc->starttime = time (0); dcc->fastsend = prefs.hex_dcc_fast_send; - snprintf (host, sizeof (host), "%s:%d", net_ip (dcc->addr), dcc->port); + g_snprintf (host, sizeof (host), "%s:%d", net_ip (dcc->addr), dcc->port); switch (dcc->type) { @@ -1638,8 +1592,7 @@ dcc_accept (GIOChannel *source, GIOCondition condition, struct DCC *dcc) case TYPE_CHATSEND: dcc_open_query (dcc->serv, dcc->nick); dcc->iotag = fe_input_add (dcc->sok, FIA_READ|FIA_EX, dcc_read_chat, dcc); - dcc->dccchat = malloc (sizeof (struct dcc_chat)); - dcc->dccchat->pos = 0; + dcc->dccchat = g_new0 (struct dcc_chat, 1); EMIT_SIGNAL (XP_TE_DCCCONCHAT, dcc->serv->front_session, dcc->nick, host, NULL, NULL, 0); break; @@ -1762,7 +1715,7 @@ dcc_listen_init (struct DCC *dcc, session *sess) static struct session *dccsess; static char *dccto; /* lame!! */ -static int dccmaxcps; +static gint64 dccmaxcps; static int recursive = FALSE; static void @@ -1772,21 +1725,25 @@ dcc_send_wild (char *file) } 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]; - GStatBuf st; + GFileInfo *file_info; + GFile *file; 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 wild[256]; - safe_strcpy (wild, file_part (file), sizeof (wild)); - path_part (file, path, sizeof (path)); + safe_strcpy (wild, file_part (filename), sizeof (wild)); + path_part (filename, path, sizeof (path)); if (path[0] != '/' || path[1] != '\0') path[strlen (path) - 1] = 0; /* remove trailing slash */ @@ -1794,7 +1751,7 @@ dcc_send (struct session *sess, char *to, char *file, int maxcps, int passive) dccto = to; dccmaxcps = maxcps; - free (file); + g_free (filename); recursive = TRUE; for_files (path, wild, dcc_send_wild); @@ -1806,91 +1763,135 @@ dcc_send (struct session *sess, char *to, char *file, int maxcps, int passive) dcc = new_dcc (); if (!dcc) { - free (file); + g_free (filename); return; } - dcc->file = file; + + dcc->file = filename; 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 - if (sizeof (st.st_size) > 4 && st.st_size > 4294967295U) - { - PrintText (sess, "Cannot send files larger than 4 GB.\n"); - goto xit; - } -#endif + dcc_close (dcc, 0, TRUE); /* dcc_close will free dcc->file */ - if (!(*file_part (file)) || S_ISDIR (st.st_mode) || st.st_size < 1) - { - PrintText (sess, "Cannot send directories or empty files.\n"); - goto xit; - } + return; + } - dcc->starttime = dcc->offertime = time (0); - dcc->serv = sess->server; - dcc->dccstat = STAT_QUEUED; - dcc->size = st.st_size; - dcc->type = TYPE_SEND; - dcc->fp = g_open (file, OFLAGS | O_RDONLY, 0); - if (dcc->fp != -1) - { - if (passive || dcc_listen_init (dcc, sess)) - { - char havespaces = 0; - while (*file) - { - if (*file == ' ') - { - if (prefs.hex_dcc_send_fillspaces) - *file = '_'; - else - havespaces = 1; - } - file++; - } - 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); + file = g_file_new_for_path (filename_fs); + if (file == NULL) + { + PrintTextf (sess, _("Cannot access %s\n"), dcc->file); + PrintTextf (sess, "%s %d: %s\n", _("Error"), errno, errorstring (errno)); - if (passive) - { - dcc->pasvid = new_id(); - snprintf (outbuf, sizeof (outbuf), (havespaces) ? - "DCC SEND \"%s\" 199 0 %" DCC_SFMT " %d" : - "DCC SEND %s 199 0 %" DCC_SFMT " %d", - file_part (dcc->file), - dcc->size, dcc->pasvid); - } - else - { - snprintf (outbuf, sizeof (outbuf), (havespaces) ? - "DCC SEND \"%s\" %u %d %"DCC_SFMT : - "DCC SEND %s %u %d %"DCC_SFMT, - file_part (dcc->file), dcc->addr, - dcc->port, dcc->size); - } - sess->server->p_ctcp (sess->server, to, outbuf); + dcc_close (dcc, 0, TRUE); /* dcc_close will free dcc->file */ - EMIT_SIGNAL (XP_TE_DCCOFFER, sess, file_part (dcc->file), - to, dcc->file, NULL, 0); - } else + g_free (filename_fs); + + return; + } + + file_info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SIZE "," G_FILE_ATTRIBUTE_STANDARD_TYPE, G_FILE_QUERY_INFO_NONE, NULL, NULL); + + g_object_unref (file); + + if (file_info == NULL) + { + PrintTextf (sess, _("Cannot access %s\n"), dcc->file); + PrintTextf (sess, "%s %d: %s\n", _("Error"), errno, errorstring (errno)); + + dcc_close (dcc, 0, TRUE); /* dcc_close will free dcc->file */ + + g_free (filename_fs); + + return; + } + + file_type = g_file_info_get_file_type (file_info); + file_size = g_file_info_get_size (file_info); + + g_object_unref (file_info); + + if (*file_part (filename) == '\0' || file_type == G_FILE_TYPE_DIRECTORY || file_size <= 0) + { + PrintText (sess, "Cannot send directories or empty files.\n"); + + dcc_close (dcc, 0, TRUE); /* dcc_close will free dcc->file */ + + g_free (filename_fs); + + return; + } + + dcc->starttime = dcc->offertime = time (0); + dcc->serv = sess->server; + dcc->dccstat = STAT_QUEUED; + dcc->size = file_size; + dcc->type = TYPE_SEND; + dcc->fp = g_open (filename_fs, OFLAGS | O_RDONLY, 0); + + g_free (filename_fs); + + if (dcc->fp == -1) + { + PrintText (sess, "Cannot send directories or empty files.\n"); + + dcc_close (dcc, 0, TRUE); /* dcc_close will free dcc->file */ + + return; + } + + if (passive || dcc_listen_init (dcc, sess)) + { + char havespaces = 0; + while (*filename) + { + if (*filename == ' ') { - dcc_close (dcc, 0, TRUE); + if (prefs.hex_dcc_send_fillspaces) + *filename = '_'; + else + havespaces = 1; } - return; + filename++; } + dcc->nick = g_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(); + g_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 + { + g_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 * @@ -1906,7 +1907,7 @@ find_dcc_from_id (int id, int type) return dcc; list = list->next; } - return 0; + return NULL; } static struct DCC * @@ -1922,7 +1923,7 @@ find_dcc_from_port (int port, int type) return dcc; list = list->next; } - return 0; + return NULL; } struct DCC * @@ -1947,7 +1948,7 @@ find_dcc (char *nick, char *file, int type) } list = list->next; } - return 0; + return NULL; } /* called when we receive a NICK change from server */ @@ -1965,9 +1966,8 @@ dcc_change_nick (struct server *serv, char *oldnick, char *newnick) { if (!serv->p_cmp (dcc->nick, oldnick)) { - if (dcc->nick) - free (dcc->nick); - dcc->nick = strdup (newnick); + g_free (dcc->nick); + dcc->nick = g_strdup (newnick); } } list = list->next; @@ -1976,68 +1976,153 @@ dcc_change_nick (struct server *serv, char *oldnick, char *newnick) /* 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) { -#ifndef WIN32 - GStatBuf st_a, st_b; -#endif + gboolean result = FALSE; + gchar *filename_fs = NULL, *new_filename_fs = NULL; + 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 (strcmp (dcc->destfile, new_dcc->destfile) == 0) + { return TRUE; + } - /* now handle case-insensitive Filesystems: HFS+, FAT */ -#ifdef WIN32 - /* warning no win32 implementation - behaviour may be unreliable */ -#else - /* 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; + filename_fs = g_filename_from_utf8 (dcc->file, -1, NULL, NULL, NULL); + if (filename_fs == NULL) + { + goto exit; + } - /* same inode, same device, same file! */ - if (st_a.st_ino == st_b.st_ino && - st_a.st_dev == st_b.st_dev) - return TRUE; -#endif + new_filename_fs = g_filename_from_utf8 (new_dcc->file, -1, NULL, NULL, NULL); + if (new_filename_fs == NULL) + { + goto exit; + } - 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 (new_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: + g_free (filename_fs); + 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); + } + + g_free (file_id); + g_free (new_file_id); + g_free(filesystem_id); + g_free(new_filesystem_id); + + return result; } -static int -is_resumable (struct DCC *dcc) +static void +update_is_resumable (struct DCC *dcc) { + gchar *filename_fs = g_filename_from_utf8 (dcc->destfile, -1, NULL, NULL, NULL); + dcc->resumable = 0; /* 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; - - if (g_stat (dcc->destfile, &st) != -1) + GFile *file = g_file_new_for_path (filename_fs); + if (file != NULL) { - 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; - dcc->pos = st.st_size; + goffset file_size_offset = g_file_info_get_size (file_info); + 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 - dcc->resume_error = 2; - } else + { + dcc->resume_errno = errno; + dcc->resume_error = 1; + } + + g_object_unref(file); + } + else { dcc->resume_errno = errno; dcc->resume_error = 1; } - } else + } + else { dcc->resume_errno = errno; dcc->resume_error = 1; } /* Now verify that this DCC is not already in progress from someone else */ - if (dcc->resumable) { GSList *list = dcc_list; @@ -2059,8 +2144,6 @@ is_resumable (struct DCC *dcc) list = list->next; } } - - return dcc->resumable; } void @@ -2100,7 +2183,7 @@ dcc_get_with_destfile (struct DCC *dcc, char *file) dcc->destfile = g_strdup (file); /* utf-8 */ /* since destfile changed, must check resumability again */ - is_resumable (dcc); + update_is_resumable (dcc); dcc_get (dcc); } @@ -2133,14 +2216,11 @@ dcc_get_nick (struct session *sess, char *nick) static struct DCC * new_dcc (void) { - struct DCC *dcc = malloc (sizeof (struct DCC)); - if (!dcc) - return 0; - memset (dcc, 0, sizeof (struct DCC)); + struct DCC *dcc = g_new0 (struct DCC, 1); dcc->sok = -1; dcc->fp = -1; dcc_list = g_slist_prepend (dcc_list, dcc); - return (dcc); + return dcc; } void @@ -2187,7 +2267,7 @@ dcc_chat (struct session *sess, char *nick, int passive) dcc->serv = sess->server; dcc->dccstat = STAT_QUEUED; dcc->type = TYPE_CHATSEND; - dcc->nick = strdup (nick); + dcc->nick = g_strdup (nick); if (passive || dcc_listen_init (dcc, sess)) { if (prefs.hex_gui_autoopen_chat) @@ -2200,11 +2280,11 @@ dcc_chat (struct session *sess, char *nick, int passive) if (passive) { dcc->pasvid = new_id (); - snprintf (outbuf, sizeof (outbuf), "DCC CHAT chat 199 %d %d", + g_snprintf (outbuf, sizeof (outbuf), "DCC CHAT chat 199 %d %d", dcc->port, dcc->pasvid); } else { - snprintf (outbuf, sizeof (outbuf), "DCC CHAT chat %u %d", + g_snprintf (outbuf, sizeof (outbuf), "DCC CHAT chat %u %d", dcc->addr, dcc->port); } dcc->serv->p_ctcp (dcc->serv, nick, outbuf); @@ -2230,9 +2310,9 @@ dcc_resume (struct DCC *dcc) { dcc->resume_sent = 1; /* filename contains spaces? Quote them! */ - snprintf (tbuf, sizeof (tbuf) - 10, strchr (dcc->file, ' ') ? - "DCC RESUME \"%s\" %d %"DCC_SFMT : - "DCC RESUME %s %d %"DCC_SFMT, + g_snprintf (tbuf, sizeof (tbuf) - 10, strchr (dcc->file, ' ') ? + "DCC RESUME \"%s\" %d %" G_GUINT64_FORMAT : + "DCC RESUME %s %d %" G_GUINT64_FORMAT, dcc->file, dcc->port, dcc->resumable); if (dcc->pasvid) @@ -2287,7 +2367,7 @@ dcc_add_chat (session *sess, char *nick, int port, guint32 addr, int pasvid) dcc->addr = addr; dcc->port = port; dcc->pasvid = pasvid; - dcc->nick = strdup (nick); + dcc->nick = g_strdup (nick); dcc->starttime = time (0); EMIT_SIGNAL (XP_TE_DCCCHATOFFER, sess->server->front_session, nick, @@ -2307,7 +2387,7 @@ dcc_add_chat (session *sess, char *nick, int port, guint32 addr, int pasvid) else { char buff[128]; - snprintf (buff, sizeof (buff), "%s is offering DCC Chat. Do you want to accept?", nick); + g_snprintf (buff, sizeof (buff), "%s is offering DCC Chat. Do you want to accept?", nick); fe_confirm (buff, dcc_confirm_chat, dcc_deny_chat, dcc); } } @@ -2316,7 +2396,7 @@ dcc_add_chat (session *sess, char *nick, int port, guint32 addr, int pasvid) } 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; char tbuf[512]; @@ -2324,7 +2404,7 @@ dcc_add_file (session *sess, char *file, DCC_SIZE size, int port, char *nick, gu dcc = new_dcc (); if (dcc) { - dcc->file = strdup (file); + dcc->file = g_strdup (file); dcc->destfile = g_malloc (strlen (prefs.hex_dcc_dir) + strlen (nick) + strlen (file) + 4); @@ -2359,14 +2439,14 @@ dcc_add_file (session *sess, char *file, DCC_SIZE size, int port, char *nick, gu dcc->port = port; dcc->pasvid = pasvid; dcc->size = size; - dcc->nick = strdup (nick); + dcc->nick = g_strdup (nick); dcc->maxcps = prefs.hex_dcc_max_get_cps; - is_resumable (dcc); + update_is_resumable (dcc); if (prefs.hex_dcc_auto_recv == 1) { - snprintf (tbuf, sizeof (tbuf), _("%s is offering \"%s\". Do you want to accept?"), nick, file); + g_snprintf (tbuf, sizeof (tbuf), _("%s is offering \"%s\". Do you want to accept?"), nick, file); fe_confirm (tbuf, dcc_confirm_send, dcc_deny_send, dcc); } else if (prefs.hex_dcc_auto_recv == 2) @@ -2380,8 +2460,8 @@ dcc_add_file (session *sess, char *file, DCC_SIZE size, int port, char *nick, gu } else fe_dcc_add (dcc); } - sprintf (tbuf, "%"DCC_SFMT, size); - snprintf (tbuf + 24, 300, "%s:%d", net_ip (addr), port); + sprintf (tbuf, "%" G_GUINT64_FORMAT, size); + g_snprintf (tbuf + 24, 300, "%s:%d", net_ip (addr), port); EMIT_SIGNAL (XP_TE_DCCSENDOFFER, sess->server->front_session, nick, file, tbuf, tbuf + 24, 0); @@ -2397,7 +2477,7 @@ handle_dcc (struct session *sess, char *nick, char *word[], char *word_eol[], char *type = word[5]; int port, pasvid = 0; guint32 addr; - DCC_SIZE size; + guint64 size; int psend = 0; if (!g_ascii_strcasecmp (type, "CHAT")) @@ -2463,7 +2543,7 @@ handle_dcc (struct session *sess, char *nick, char *word[], char *word_eol[], dcc = find_dcc (nick, word[6], TYPE_SEND); if (dcc) { - size = BIG_STR_TO_INT (word[8]); + size = g_ascii_strtoull (word[8], NULL, 10); dcc->resumable = size; if (dcc->resumable < dcc->size) { @@ -2473,19 +2553,19 @@ handle_dcc (struct session *sess, char *nick, char *word[], char *word_eol[], /* Checking if dcc is passive and if filename contains spaces */ if (dcc->pasvid) - snprintf (tbuf, sizeof (tbuf), strchr (file_part (dcc->file), ' ') ? - "DCC ACCEPT \"%s\" %d %"DCC_SFMT" %d" : - "DCC ACCEPT %s %d %"DCC_SFMT" %d", + g_snprintf (tbuf, sizeof (tbuf), strchr (file_part (dcc->file), ' ') ? + "DCC ACCEPT \"%s\" %d %" G_GUINT64_FORMAT " %d" : + "DCC ACCEPT %s %d %" G_GUINT64_FORMAT " %d", file_part (dcc->file), port, dcc->resumable, dcc->pasvid); else - snprintf (tbuf, sizeof (tbuf), strchr (file_part (dcc->file), ' ') ? - "DCC ACCEPT \"%s\" %d %"DCC_SFMT : - "DCC ACCEPT %s %d %"DCC_SFMT, + g_snprintf (tbuf, sizeof (tbuf), strchr (file_part (dcc->file), ' ') ? + "DCC ACCEPT \"%s\" %d %" G_GUINT64_FORMAT : + "DCC ACCEPT %s %d %" G_GUINT64_FORMAT, file_part (dcc->file), port, dcc->resumable); 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, file_part (dcc->file), tbuf, NULL, 0, tags_data->timestamp); @@ -2508,7 +2588,7 @@ handle_dcc (struct session *sess, char *nick, char *word[], char *word_eol[], port = atoi (word[8]); 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 */ pasvid = atoi (word[10]); @@ -2576,7 +2656,7 @@ dcc_show_list (struct session *sess) { dcc = (struct DCC *) list->data; 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, _(dccstat[dcc->dccstat].name), dcc->size, dcc->pos, file_part (dcc->file)); |