2 * Copyright (C) 1998-2006 Peter Zelezny.
3 * Copyright (C) 2006 Damjan Jovanovic
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
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
22 * 2001-03-08 Added support for getting "dcc_ip" config parameter.
23 * Jim Seymour (jseymour@LinxNet.com)
26 /* we only use 32 bits, but without this define, you get only 31! */
27 #define _FILE_OFFSET_BITS 64
55 #define BIG_STR_TO_INT(x) strtoull(x,NULL,10)
57 #define BIG_STR_TO_INT(x) strtoul(x,NULL,10)
60 static char *dcctypes
[] = { "SEND", "RECV", "CHAT", "CHAT" };
62 struct dccstat_info dccstat
[] = {
63 {N_("Waiting"), 1 /*black */ },
64 {N_("Active"), 12 /*cyan */ },
65 {N_("Failed"), 4 /*red */ },
66 {N_("Done"), 3 /*green */ },
67 {N_("Connect"), 1 /*black */ },
68 {N_("Aborted"), 4 /*red */ },
71 static int dcc_global_throttle
; /* 0x1 = sends, 0x2 = gets */
72 /*static*/ int dcc_sendcpssum
, dcc_getcpssum
;
74 static struct DCC
*new_dcc (void);
75 static void dcc_close (struct DCC
*dcc
, int dccstat
, int destroy
);
76 static gboolean
dcc_send_data (GIOChannel
*, GIOCondition
, struct DCC
*);
77 static gboolean
dcc_read (GIOChannel
*, GIOCondition
, struct DCC
*);
78 static gboolean
dcc_read_ack (GIOChannel
*source
, GIOCondition condition
, struct DCC
*dcc
);
85 /* start the first ID at a random number for pseudo security */
87 id
= RAND_INT(255) + 1;
88 /* ignore overflows, since it can go to 2 billion */
94 timeval_diff (GTimeVal
*greater
,
100 result
= greater
->tv_sec
- less
->tv_sec
;
101 usecdiff
= (long) greater
->tv_usec
- less
->tv_usec
;
102 result
+= (double) usecdiff
/ 1000000;
108 dcc_unthrottle (struct DCC
*dcc
)
110 /* don't unthrottle here, but delegate to funcs */
111 if (dcc
->type
== TYPE_RECV
)
112 dcc_read (NULL
, 0, dcc
);
114 dcc_send_data (NULL
, 0, dcc
);
118 dcc_calc_cps (struct DCC
*dcc
)
122 double timediff
, startdiff
;
123 int glob_throttle_bit
, wasthrottled
;
124 int *cpssum
, glob_limit
;
125 DCC_SIZE pos
, posdiff
;
127 g_get_current_time (&now
);
129 /* the pos we use for sends is an average
130 between pos and ack */
131 if (dcc
->type
== TYPE_SEND
)
133 /* carefull to avoid 32bit overflow */
134 pos
= dcc
->pos
- ((dcc
->pos
- dcc
->ack
) / 2);
135 glob_throttle_bit
= 0x1;
136 cpssum
= &dcc_sendcpssum
;
137 glob_limit
= prefs
.dcc_global_max_send_cps
;
142 glob_throttle_bit
= 0x2;
143 cpssum
= &dcc_getcpssum
;
144 glob_limit
= prefs
.dcc_global_max_get_cps
;
147 if (!dcc
->firstcpstv
.tv_sec
&& !dcc
->firstcpstv
.tv_usec
)
148 dcc
->firstcpstv
= now
;
151 startdiff
= timeval_diff (&now
, &dcc
->firstcpstv
);
154 else if (startdiff
> CPS_AVG_WINDOW
)
155 startdiff
= CPS_AVG_WINDOW
;
157 timediff
= timeval_diff (&now
, &dcc
->lastcpstv
);
158 if (timediff
> startdiff
)
159 timediff
= startdiff
= 1;
161 posdiff
= pos
- dcc
->lastcpspos
;
163 dcc
->cps
= ((double) posdiff
/ timediff
) * (timediff
/ startdiff
) +
164 (double) dcc
->cps
* (1.0 - (timediff
/ startdiff
));
166 *cpssum
+= dcc
->cps
- oldcps
;
169 dcc
->lastcpspos
= pos
;
170 dcc
->lastcpstv
= now
;
172 /* now check cps against set limits... */
173 wasthrottled
= dcc
->throttled
;
175 /* check global limits first */
176 dcc
->throttled
&= ~0x2;
177 if (glob_limit
> 0 && *cpssum
>= glob_limit
)
179 dcc_global_throttle
|= glob_throttle_bit
;
180 if (dcc
->maxcps
>= 0)
181 dcc
->throttled
|= 0x2;
184 dcc_global_throttle
&= ~glob_throttle_bit
;
186 /* now check per-connection limit */
187 if (dcc
->maxcps
> 0 && dcc
->cps
> dcc
->maxcps
)
188 dcc
->throttled
|= 0x1;
190 dcc
->throttled
&= ~0x1;
193 if (wasthrottled
&& !dcc
->throttled
)
194 dcc_unthrottle (dcc
);
198 dcc_remove_from_sum (struct DCC
*dcc
)
200 if (dcc
->dccstat
!= STAT_ACTIVE
)
202 if (dcc
->type
== TYPE_SEND
)
203 dcc_sendcpssum
-= dcc
->cps
;
204 else if (dcc
->type
== TYPE_RECV
)
205 dcc_getcpssum
-= dcc
->cps
;
209 is_dcc (struct DCC
*dcc
)
211 GSList
*list
= dcc_list
;
214 if (list
->data
== dcc
)
221 /* this is called from xchat.c:xchat_misc_checks() every 1 second. */
224 dcc_check_timeouts (void)
227 time_t tim
= time (0);
228 GSList
*next
, *list
= dcc_list
;
232 dcc
= (struct DCC
*) list
->data
;
235 switch (dcc
->dccstat
)
241 if (dcc
->type
== TYPE_SEND
|| dcc
->type
== TYPE_RECV
)
243 if (prefs
.dccstalltimeout
> 0)
246 && tim
- dcc
->lasttime
> prefs
.dccstalltimeout
)
248 EMIT_SIGNAL (XP_TE_DCCSTALL
, dcc
->serv
->front_session
,
250 file_part (dcc
->file
), dcc
->nick
, NULL
, 0);
251 dcc_close (dcc
, STAT_ABORTED
, FALSE
);
257 if (dcc
->type
== TYPE_SEND
|| dcc
->type
== TYPE_CHATSEND
)
259 if (tim
- dcc
->offertime
> prefs
.dcctimeout
)
261 if (prefs
.dcctimeout
> 0)
263 EMIT_SIGNAL (XP_TE_DCCTOUT
, dcc
->serv
->front_session
,
265 file_part (dcc
->file
), dcc
->nick
, NULL
, 0);
266 dcc_close (dcc
, STAT_ABORTED
, FALSE
);
274 if (prefs
.dcc_remove
)
275 dcc_close (dcc
, 0, TRUE
);
283 dcc_lookup_proxy (char *host
, struct sockaddr_in
*addr
)
286 static char *cache_host
= NULL
;
287 static guint32 cache_addr
;
289 /* too lazy to thread this, so we cache results */
292 if (strcmp (host
, cache_host
) == 0)
294 memcpy (&addr
->sin_addr
, &cache_addr
, 4);
301 h
= gethostbyname (host
);
302 if (h
!= NULL
&& h
->h_length
== 4 && h
->h_addr_list
[0] != NULL
)
304 memcpy (&addr
->sin_addr
, h
->h_addr
, 4);
305 memcpy (&cache_addr
, h
->h_addr
, 4);
306 cache_host
= strdup (host
);
313 #define DCC_USE_PROXY() (prefs.proxy_host[0] && prefs.proxy_type>0 && prefs.proxy_type<5 && prefs.proxy_use!=1)
316 dcc_connect_sok (struct DCC
*dcc
)
319 struct sockaddr_in addr
;
321 sok
= socket (AF_INET
, SOCK_STREAM
, 0);
325 memset (&addr
, 0, sizeof (addr
));
326 addr
.sin_family
= AF_INET
;
327 if (DCC_USE_PROXY ())
329 if (!dcc_lookup_proxy (prefs
.proxy_host
, &addr
))
334 addr
.sin_port
= htons (prefs
.proxy_port
);
338 addr
.sin_port
= htons (dcc
->port
);
339 addr
.sin_addr
.s_addr
= htonl (dcc
->addr
);
342 set_nonblocking (sok
);
343 connect (sok
, (struct sockaddr
*) &addr
, sizeof (addr
));
349 dcc_close (struct DCC
*dcc
, int dccstat
, int destroy
)
353 fe_input_remove (dcc
->wiotag
);
359 fe_input_remove (dcc
->iotag
);
365 closesocket (dcc
->sok
);
369 dcc_remove_from_sum (dcc
);
376 if(dccstat
== STAT_DONE
)
378 /* if we just completed a dcc recieve, move the */
379 /* completed file to the completed directory */
380 if(dcc
->type
== TYPE_RECV
)
382 /* mgl: change this to use destfile_fs for correctness and to */
383 /* handle the case where dccwithnick is set */
384 move_file_utf8 (prefs
.dccdir
, prefs
.dcc_completed_dir
,
385 file_part (dcc
->destfile
), prefs
.dccpermissions
);
391 dcc
->dccstat
= dccstat
;
400 dcc_list
= g_slist_remove (dcc_list
, dcc
);
407 g_free (dcc
->destfile
);
408 if (dcc
->destfile_fs
)
409 g_free (dcc
->destfile_fs
);
419 dcc_abort (session
*sess
, struct DCC
*dcc
)
423 switch (dcc
->dccstat
)
426 case STAT_CONNECTING
:
428 dcc_close (dcc
, STAT_ABORTED
, FALSE
);
433 EMIT_SIGNAL (XP_TE_DCCCHATABORT
, sess
, dcc
->nick
, NULL
, NULL
,
437 EMIT_SIGNAL (XP_TE_DCCSENDABORT
, sess
, dcc
->nick
,
438 file_part (dcc
->file
), NULL
, NULL
, 0);
441 EMIT_SIGNAL (XP_TE_DCCRECVABORT
, sess
, dcc
->nick
,
442 dcc
->file
, NULL
, NULL
, 0);
446 dcc_close (dcc
, 0, TRUE
);
452 dcc_notify_kill (struct server
*serv
)
454 struct server
*replaceserv
= 0;
456 GSList
*list
= dcc_list
;
458 replaceserv
= (struct server
*) serv_list
->data
;
461 dcc
= (struct DCC
*) list
->data
;
462 if (dcc
->serv
== serv
)
463 dcc
->serv
= replaceserv
;
469 dcc_write_chat (char *nick
, char *text
)
474 dcc
= find_dcc (nick
, "", TYPE_CHATRECV
);
476 dcc
= find_dcc (nick
, "", TYPE_CHATSEND
);
477 if (dcc
&& dcc
->dccstat
== STAT_ACTIVE
)
480 tcp_send_real (NULL
, dcc
->sok
, dcc
->serv
->encoding
, dcc
->serv
->using_irc
,
482 send (dcc
->sok
, "\n", 1, 0);
491 1 - the dcc is closed! */
494 dcc_chat_line (struct DCC
*dcc
, char *line
)
497 char *word
[PDIWORDS
];
507 if (dcc
->serv
->using_cp1255
)
508 len
++; /* include the NUL terminator */
510 if (dcc
->serv
->using_irc
) /* using "IRC" encoding (CP1252/UTF-8 hybrid) */
512 else if (dcc
->serv
->encoding
== NULL
) /* system */
513 utf
= g_locale_to_utf8 (line
, len
, NULL
, &utf_len
, NULL
);
515 utf
= g_convert (line
, len
, "UTF-8", dcc
->serv
->encoding
, 0, &utf_len
, 0);
523 if (dcc
->serv
->using_cp1255
&& len
> 0)
526 /* we really need valid UTF-8 now */
527 conv
= text_validate (&line
, &len
);
529 sess
= find_dialog (dcc
->serv
, dcc
->nick
);
531 sess
= dcc
->serv
->front_session
;
533 sprintf (portbuf
, "%d", dcc
->port
);
535 word
[0] = "DCC Chat Text";
536 word
[1] = net_ip (dcc
->addr
);
540 for (i
= 5; i
< PDIWORDS
; i
++)
543 ret
= plugin_emit_print (sess
, word
);
545 /* did the plugin close it? */
546 if (!g_slist_find (dcc_list
, dcc
))
555 /* did the plugin eat the event? */
565 url_check_line (line
, len
);
567 if (line
[0] == 1 && !strncasecmp (line
+ 1, "ACTION", 6))
569 po
= strchr (line
+ 8, '\001');
572 inbound_action (sess
, dcc
->serv
->nick
, dcc
->nick
, "", line
+ 8, FALSE
, FALSE
);
575 inbound_privmsg (dcc
->serv
, dcc
->nick
, "", line
, FALSE
);
585 dcc_read_chat (GIOChannel
*source
, GIOCondition condition
, struct DCC
*dcc
)
595 fe_input_remove (dcc
->iotag
);
601 dcc
->iotag
= fe_input_add (dcc
->sok
, FIA_READ
|FIA_EX
, dcc_read_chat
, dcc
);
603 len
= recv (dcc
->sok
, lbuf
, sizeof (lbuf
) - 2, 0);
611 sprintf (portbuf
, "%d", dcc
->port
);
612 EMIT_SIGNAL (XP_TE_DCCCHATF
, dcc
->serv
->front_session
, dcc
->nick
,
613 net_ip (dcc
->addr
), portbuf
,
614 errorstring ((len
< 0) ? sock_error () : 0), 0);
615 dcc_close (dcc
, STAT_FAILED
, FALSE
);
627 dcc
->dccchat
->linebuf
[dcc
->dccchat
->pos
] = 0;
628 dead
= dcc_chat_line (dcc
, dcc
->dccchat
->linebuf
);
630 if (dead
|| !dcc
->dccchat
) /* the dcc has been closed, don't use (DCC *)! */
633 dcc
->pos
+= dcc
->dccchat
->pos
;
634 dcc
->dccchat
->pos
= 0;
638 dcc
->dccchat
->linebuf
[dcc
->dccchat
->pos
] = lbuf
[i
];
639 if (dcc
->dccchat
->pos
< (sizeof (dcc
->dccchat
->linebuf
) - 1))
648 dcc_calc_average_cps (struct DCC
*dcc
)
652 sec
= time (0) - dcc
->starttime
;
655 if (dcc
->type
== TYPE_SEND
)
656 dcc
->cps
= (dcc
->ack
- dcc
->resumable
) / sec
;
658 dcc
->cps
= (dcc
->pos
- dcc
->resumable
) / sec
;
662 dcc_send_ack (struct DCC
*dcc
)
664 /* send in 32-bit big endian */
665 guint32 pos
= htonl (dcc
->pos
& 0xffffffff);
666 send (dcc
->sok
, (char *) &pos
, 4, 0);
670 dcc_read (GIOChannel
*source
, GIOCondition condition
, struct DCC
*dcc
)
675 gboolean need_ack
= FALSE
;
680 /* try to create the download dir (even if it exists, no harm) */
681 mkdir_utf8 (prefs
.dccdir
);
685 dcc
->fp
= open (dcc
->destfile_fs
, O_WRONLY
| O_APPEND
| OFLAGS
);
686 dcc
->pos
= dcc
->resumable
;
687 dcc
->ack
= dcc
->resumable
;
690 if (access (dcc
->destfile_fs
, F_OK
) == 0)
696 snprintf (buf
, sizeof (buf
), "%s.%d", dcc
->destfile_fs
, n
);
698 while (access (buf
, F_OK
) == 0);
700 g_free (dcc
->destfile_fs
);
701 dcc
->destfile_fs
= g_strdup (buf
);
704 dcc
->destfile
= xchat_filename_to_utf8 (buf
, -1, 0, 0, 0);
706 EMIT_SIGNAL (XP_TE_DCCRENAME
, dcc
->serv
->front_session
,
707 old
, dcc
->destfile
, NULL
, NULL
, 0);
711 open (dcc
->destfile_fs
, OFLAGS
| O_TRUNC
| O_WRONLY
| O_CREAT
,
712 prefs
.dccpermissions
);
717 /* the last executed function is open(), errno should be valid */
718 EMIT_SIGNAL (XP_TE_DCCFILEERR
, dcc
->serv
->front_session
, dcc
->destfile
,
719 errorstring (errno
), NULL
, NULL
, 0);
720 dcc_close (dcc
, STAT_FAILED
, FALSE
);
730 fe_input_remove (dcc
->iotag
);
736 dcc
->iotag
= fe_input_add (dcc
->sok
, FIA_READ
|FIA_EX
, dcc_read
, dcc
);
738 n
= recv (dcc
->sok
, buf
, sizeof (buf
), 0);
750 EMIT_SIGNAL (XP_TE_DCCRECVERR
, dcc
->serv
->front_session
, dcc
->file
,
751 dcc
->destfile
, dcc
->nick
,
752 errorstring ((n
< 0) ? sock_error () : 0), 0);
753 /* send ack here? but the socket is dead */
755 dcc_send_ack (dcc);*/
756 dcc_close (dcc
, STAT_FAILED
, FALSE
);
760 if (write (dcc
->fp
, buf
, n
) == -1) /* could be out of hdd space */
762 EMIT_SIGNAL (XP_TE_DCCRECVERR
, dcc
->serv
->front_session
, dcc
->file
,
763 dcc
->destfile
, dcc
->nick
, errorstring (errno
), 0);
766 dcc_close (dcc
, STAT_FAILED
, FALSE
);
770 dcc
->lasttime
= time (0);
772 need_ack
= TRUE
; /* send ack when we're done recv()ing */
774 if (dcc
->pos
>= dcc
->size
)
777 dcc_close (dcc
, STAT_DONE
, FALSE
);
778 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 */
779 sprintf (buf
, "%d", dcc
->cps
);
780 EMIT_SIGNAL (XP_TE_DCCRECVCOMP
, dcc
->serv
->front_session
,
781 dcc
->file
, dcc
->destfile
, dcc
->nick
, buf
, 0);
788 dcc_open_query (server
*serv
, char *nick
)
790 if (prefs
.autodialog
)
791 open_query (serv
, nick
, FALSE
);
795 dcc_did_connect (GIOChannel
*source
, GIOCondition condition
, struct DCC
*dcc
)
798 struct sockaddr_in addr
;
800 memset (&addr
, 0, sizeof (addr
));
801 addr
.sin_port
= htons (dcc
->port
);
802 addr
.sin_family
= AF_INET
;
803 addr
.sin_addr
.s_addr
= htonl (dcc
->addr
);
805 /* check if it's already connected; This always fails on winXP */
806 if (connect (dcc
->sok
, (struct sockaddr
*) &addr
, sizeof (addr
)) != 0)
811 EMIT_SIGNAL (XP_TE_DCCCONFAIL
, dcc
->serv
->front_session
,
812 dcctypes
[dcc
->type
], dcc
->nick
, errorstring (er
),
814 dcc
->dccstat
= STAT_FAILED
;
824 dcc_connect_finished (GIOChannel
*source
, GIOCondition condition
, struct DCC
*dcc
)
830 fe_input_remove (dcc
->iotag
);
834 if (!dcc_did_connect (source
, condition
, dcc
))
837 dcc
->dccstat
= STAT_ACTIVE
;
838 snprintf (host
, sizeof host
, "%s:%d", net_ip (dcc
->addr
), dcc
->port
);
843 dcc
->iotag
= fe_input_add (dcc
->sok
, FIA_READ
|FIA_EX
, dcc_read
, dcc
);
844 EMIT_SIGNAL (XP_TE_DCCCONRECV
, dcc
->serv
->front_session
,
845 dcc
->nick
, host
, dcc
->file
, NULL
, 0);
849 dcc
->fastsend
= prefs
.fastdccsend
;
851 dcc
->wiotag
= fe_input_add (dcc
->sok
, FIA_WRITE
, dcc_send_data
, dcc
);
852 dcc
->iotag
= fe_input_add (dcc
->sok
, FIA_READ
|FIA_EX
, dcc_read_ack
, dcc
);
853 dcc_send_data (NULL
, 0, (gpointer
)dcc
);
854 EMIT_SIGNAL (XP_TE_DCCCONSEND
, dcc
->serv
->front_session
,
855 dcc
->nick
, host
, dcc
->file
, NULL
, 0);
857 case TYPE_CHATSEND
: /* pchat */
858 dcc_open_query (dcc
->serv
, dcc
->nick
);
859 case TYPE_CHATRECV
: /* normal chat */
860 dcc
->iotag
= fe_input_add (dcc
->sok
, FIA_READ
|FIA_EX
, dcc_read_chat
, dcc
);
861 dcc
->dccchat
= malloc (sizeof (struct dcc_chat
));
862 dcc
->dccchat
->pos
= 0;
863 EMIT_SIGNAL (XP_TE_DCCCONCHAT
, dcc
->serv
->front_session
,
864 dcc
->nick
, host
, NULL
, NULL
, 0);
867 dcc
->starttime
= time (0);
868 dcc
->lasttime
= dcc
->starttime
;
875 read_proxy (struct DCC
*dcc
)
877 struct proxy_state
*proxy
= dcc
->proxy
;
878 while (proxy
->bufferused
< proxy
->buffersize
)
880 int ret
= recv (dcc
->sok
, &proxy
->buffer
[proxy
->bufferused
],
881 proxy
->buffersize
- proxy
->bufferused
, 0);
883 proxy
->bufferused
+= ret
;
890 dcc
->dccstat
= STAT_FAILED
;
894 fe_input_remove (dcc
->iotag
);
905 write_proxy (struct DCC
*dcc
)
907 struct proxy_state
*proxy
= dcc
->proxy
;
908 while (proxy
->bufferused
< proxy
->buffersize
)
910 int ret
= send (dcc
->sok
, &proxy
->buffer
[proxy
->bufferused
],
911 proxy
->buffersize
- proxy
->bufferused
, 0);
913 proxy
->bufferused
+= ret
;
920 dcc
->dccstat
= STAT_FAILED
;
924 fe_input_remove (dcc
->wiotag
);
935 proxy_read_line (struct DCC
*dcc
)
937 struct proxy_state
*proxy
= dcc
->proxy
;
940 proxy
->buffersize
= proxy
->bufferused
+ 1;
941 if (!read_proxy (dcc
))
943 if (proxy
->buffer
[proxy
->bufferused
- 1] == '\n'
944 || proxy
->bufferused
== MAX_PROXY_BUFFER
)
946 proxy
->buffer
[proxy
->bufferused
- 1] = 0;
953 dcc_wingate_proxy_traverse (GIOChannel
*source
, GIOCondition condition
, struct DCC
*dcc
)
955 struct proxy_state
*proxy
= dcc
->proxy
;
956 if (proxy
->phase
== 0)
958 proxy
->buffersize
= snprintf ((char*) proxy
->buffer
, MAX_PROXY_BUFFER
,
959 "%s %d\r\n", net_ip(dcc
->addr
),
961 proxy
->bufferused
= 0;
962 dcc
->wiotag
= fe_input_add (dcc
->sok
, FIA_WRITE
|FIA_EX
,
963 dcc_wingate_proxy_traverse
, dcc
);
966 if (proxy
->phase
== 1)
968 if (!read_proxy (dcc
))
970 fe_input_remove (dcc
->wiotag
);
972 dcc_connect_finished (source
, 0, dcc
);
986 dcc_socks_proxy_traverse (GIOChannel
*source
, GIOCondition condition
, struct DCC
*dcc
)
988 struct proxy_state
*proxy
= dcc
->proxy
;
990 if (proxy
->phase
== 0)
992 struct sock_connect sc
;
995 sc
.port
= htons (dcc
->port
);
996 sc
.address
= htonl (dcc
->addr
);
997 strncpy (sc
.username
, prefs
.username
, 9);
998 memcpy (proxy
->buffer
, &sc
, sizeof (sc
));
999 proxy
->buffersize
= 8 + strlen (sc
.username
) + 1;
1000 proxy
->bufferused
= 0;
1001 dcc
->wiotag
= fe_input_add (dcc
->sok
, FIA_WRITE
|FIA_EX
,
1002 dcc_socks_proxy_traverse
, dcc
);
1006 if (proxy
->phase
== 1)
1008 if (!write_proxy (dcc
))
1010 fe_input_remove (dcc
->wiotag
);
1012 proxy
->bufferused
= 0;
1013 proxy
->buffersize
= 8;
1014 dcc
->iotag
= fe_input_add (dcc
->sok
, FIA_READ
|FIA_EX
,
1015 dcc_socks_proxy_traverse
, dcc
);
1019 if (proxy
->phase
== 2)
1021 if (!read_proxy (dcc
))
1023 fe_input_remove (dcc
->iotag
);
1025 if (proxy
->buffer
[1] == 90)
1026 dcc_connect_finished (source
, 0, dcc
);
1029 dcc
->dccstat
= STAT_FAILED
;
1030 fe_dcc_update (dcc
);
1037 struct sock5_connect1
1044 dcc_socks5_proxy_traverse (GIOChannel
*source
, GIOCondition condition
, struct DCC
*dcc
)
1046 struct proxy_state
*proxy
= dcc
->proxy
;
1047 int auth
= prefs
.proxy_auth
&& prefs
.proxy_user
[0] && prefs
.proxy_pass
[0];
1049 if (proxy
->phase
== 0)
1051 struct sock5_connect1 sc1
;
1058 memcpy (proxy
->buffer
, &sc1
, 3);
1059 proxy
->buffersize
= 3;
1060 proxy
->bufferused
= 0;
1061 dcc
->wiotag
= fe_input_add (dcc
->sok
, FIA_WRITE
|FIA_EX
,
1062 dcc_socks5_proxy_traverse
, dcc
);
1066 if (proxy
->phase
== 1)
1068 if (!write_proxy (dcc
))
1070 fe_input_remove (dcc
->wiotag
);
1072 proxy
->bufferused
= 0;
1073 proxy
->buffersize
= 2;
1074 dcc
->iotag
= fe_input_add (dcc
->sok
, FIA_READ
|FIA_EX
,
1075 dcc_socks5_proxy_traverse
, dcc
);
1079 if (proxy
->phase
== 2)
1081 if (!read_proxy (dcc
))
1083 fe_input_remove (dcc
->iotag
);
1086 /* did the server say no auth required? */
1087 if (proxy
->buffer
[0] == 5 && proxy
->buffer
[1] == 0)
1090 /* Set up authentication I/O */
1093 int len_u
=0, len_p
=0;
1095 /* authentication sub-negotiation (RFC1929) */
1096 if ( proxy
->buffer
[0] != 5 || proxy
->buffer
[1] != 2 ) /* UPA not supported by server */
1098 PrintText (dcc
->serv
->front_session
, "SOCKS\tServer doesn't support UPA authentication.\n");
1099 dcc
->dccstat
= STAT_FAILED
;
1100 fe_dcc_update (dcc
);
1104 memset (proxy
->buffer
, 0, MAX_PROXY_BUFFER
);
1106 /* form the UPA request */
1107 len_u
= strlen (prefs
.proxy_user
);
1108 len_p
= strlen (prefs
.proxy_pass
);
1109 proxy
->buffer
[0] = 1;
1110 proxy
->buffer
[1] = len_u
;
1111 memcpy (proxy
->buffer
+ 2, prefs
.proxy_user
, len_u
);
1112 proxy
->buffer
[2 + len_u
] = len_p
;
1113 memcpy (proxy
->buffer
+ 3 + len_u
, prefs
.proxy_pass
, len_p
);
1115 proxy
->buffersize
= 3 + len_u
+ len_p
;
1116 proxy
->bufferused
= 0;
1117 dcc
->wiotag
= fe_input_add (dcc
->sok
, FIA_WRITE
|FIA_EX
,
1118 dcc_socks5_proxy_traverse
, dcc
);
1123 if (proxy
->buffer
[0] != 5 || proxy
->buffer
[1] != 0)
1125 PrintText (dcc
->serv
->front_session
, "SOCKS\tAuthentication required but disabled in settings.\n");
1126 dcc
->dccstat
= STAT_FAILED
;
1127 fe_dcc_update (dcc
);
1134 if (proxy
->phase
== 3)
1136 if (!write_proxy (dcc
))
1138 fe_input_remove (dcc
->wiotag
);
1140 proxy
->buffersize
= 2;
1141 proxy
->bufferused
= 0;
1142 dcc
->iotag
= fe_input_add (dcc
->sok
, FIA_READ
|FIA_EX
,
1143 dcc_socks5_proxy_traverse
, dcc
);
1147 if (proxy
->phase
== 4)
1149 if (!read_proxy (dcc
))
1153 fe_input_remove (dcc
->iotag
);
1156 if (proxy
->buffer
[1] != 0)
1158 PrintText (dcc
->serv
->front_session
, "SOCKS\tAuthentication failed. "
1159 "Is username and password correct?\n");
1160 dcc
->dccstat
= STAT_FAILED
;
1161 fe_dcc_update (dcc
);
1167 if (proxy
->phase
== 5)
1169 proxy
->buffer
[0] = 5; /* version (socks 5) */
1170 proxy
->buffer
[1] = 1; /* command (connect) */
1171 proxy
->buffer
[2] = 0; /* reserved */
1172 proxy
->buffer
[3] = 1; /* address type (IPv4) */
1173 proxy
->buffer
[4] = (dcc
->addr
>> 24) & 0xFF; /* IP address */
1174 proxy
->buffer
[5] = (dcc
->addr
>> 16) & 0xFF;
1175 proxy
->buffer
[6] = (dcc
->addr
>> 8) & 0xFF;
1176 proxy
->buffer
[7] = (dcc
->addr
& 0xFF);
1177 proxy
->buffer
[8] = (dcc
->port
>> 8) & 0xFF; /* port */
1178 proxy
->buffer
[9] = (dcc
->port
& 0xFF);
1179 proxy
->buffersize
= 10;
1180 proxy
->bufferused
= 0;
1181 dcc
->wiotag
= fe_input_add (dcc
->sok
, FIA_WRITE
|FIA_EX
,
1182 dcc_socks5_proxy_traverse
, dcc
);
1186 if (proxy
->phase
== 6)
1188 if (!write_proxy (dcc
))
1190 fe_input_remove (dcc
->wiotag
);
1192 proxy
->buffersize
= 4;
1193 proxy
->bufferused
= 0;
1194 dcc
->iotag
= fe_input_add (dcc
->sok
, FIA_READ
|FIA_EX
,
1195 dcc_socks5_proxy_traverse
, dcc
);
1199 if (proxy
->phase
== 7)
1201 if (!read_proxy (dcc
))
1203 if (proxy
->buffer
[0] != 5 || proxy
->buffer
[1] != 0)
1205 fe_input_remove (dcc
->iotag
);
1207 if (proxy
->buffer
[1] == 2)
1208 PrintText (dcc
->serv
->front_session
, "SOCKS\tProxy refused to connect to host (not allowed).\n");
1210 PrintTextf (dcc
->serv
->front_session
, "SOCKS\tProxy failed to connect to host (error %d).\n", proxy
->buffer
[1]);
1211 dcc
->dccstat
= STAT_FAILED
;
1212 fe_dcc_update (dcc
);
1215 switch (proxy
->buffer
[3])
1217 case 1: proxy
->buffersize
+= 6; break;
1218 case 3: proxy
->buffersize
+= 1; break;
1219 case 4: proxy
->buffersize
+= 18; break;
1224 if (proxy
->phase
== 8)
1226 if (!read_proxy (dcc
))
1228 /* handle domain name case */
1229 if (proxy
->buffer
[3] == 3)
1231 proxy
->buffersize
= 5 + proxy
->buffer
[4] + 2;
1233 /* everything done? */
1234 if (proxy
->bufferused
== proxy
->buffersize
)
1236 fe_input_remove (dcc
->iotag
);
1238 dcc_connect_finished (source
, 0, dcc
);
1245 dcc_http_proxy_traverse (GIOChannel
*source
, GIOCondition condition
, struct DCC
*dcc
)
1247 struct proxy_state
*proxy
= dcc
->proxy
;
1249 if (proxy
->phase
== 0)
1252 char auth_data
[128];
1253 char auth_data2
[68];
1256 n
= snprintf (buf
, sizeof (buf
), "CONNECT %s:%d HTTP/1.0\r\n",
1257 net_ip(dcc
->addr
), dcc
->port
);
1258 if (prefs
.proxy_auth
)
1260 n2
= snprintf (auth_data2
, sizeof (auth_data2
), "%s:%s",
1261 prefs
.proxy_user
, prefs
.proxy_pass
);
1262 base64_encode (auth_data
, auth_data2
, n2
);
1263 n
+= snprintf (buf
+n
, sizeof (buf
)-n
, "Proxy-Authorization: Basic %s\r\n", auth_data
);
1265 n
+= snprintf (buf
+n
, sizeof (buf
)-n
, "\r\n");
1266 proxy
->buffersize
= n
;
1267 proxy
->bufferused
= 0;
1268 memcpy (proxy
->buffer
, buf
, proxy
->buffersize
);
1269 dcc
->wiotag
= fe_input_add (dcc
->sok
, FIA_WRITE
|FIA_EX
,
1270 dcc_http_proxy_traverse
, dcc
);
1274 if (proxy
->phase
== 1)
1276 if (!write_proxy (dcc
))
1278 fe_input_remove (dcc
->wiotag
);
1280 proxy
->bufferused
= 0;
1281 dcc
->iotag
= fe_input_add (dcc
->sok
, FIA_READ
|FIA_EX
,
1282 dcc_http_proxy_traverse
, dcc
);
1286 if (proxy
->phase
== 2)
1288 if (!proxy_read_line (dcc
))
1290 /* "HTTP/1.0 200 OK" */
1291 if (proxy
->bufferused
< 12 ||
1292 memcmp (proxy
->buffer
, "HTTP/", 5) || memcmp (proxy
->buffer
+ 9, "200", 3))
1294 fe_input_remove (dcc
->iotag
);
1296 PrintText (dcc
->serv
->front_session
, proxy
->buffer
);
1297 dcc
->dccstat
= STAT_FAILED
;
1298 fe_dcc_update (dcc
);
1301 proxy
->bufferused
= 0;
1305 if (proxy
->phase
== 3)
1309 /* read until blank line */
1310 if (proxy_read_line (dcc
))
1312 if (proxy
->bufferused
< 1 ||
1313 (proxy
->bufferused
== 2 && proxy
->buffer
[0] == '\r'))
1317 if (proxy
->bufferused
> 1)
1318 PrintText (dcc
->serv
->front_session
, proxy
->buffer
);
1319 proxy
->bufferused
= 0;
1324 fe_input_remove (dcc
->iotag
);
1326 dcc_connect_finished (source
, 0, dcc
);
1333 dcc_proxy_connect (GIOChannel
*source
, GIOCondition condition
, struct DCC
*dcc
)
1335 fe_input_remove (dcc
->iotag
);
1338 if (!dcc_did_connect (source
, condition
, dcc
))
1341 dcc
->proxy
= malloc (sizeof (struct proxy_state
));
1344 dcc
->dccstat
= STAT_FAILED
;
1345 fe_dcc_update (dcc
);
1348 memset (dcc
->proxy
, 0, sizeof (struct proxy_state
));
1350 switch (prefs
.proxy_type
)
1352 case 1: return dcc_wingate_proxy_traverse (source
, condition
, dcc
);
1353 case 2: return dcc_socks_proxy_traverse (source
, condition
, dcc
);
1354 case 3: return dcc_socks5_proxy_traverse (source
, condition
, dcc
);
1355 case 4: return dcc_http_proxy_traverse (source
, condition
, dcc
);
1360 static int dcc_listen_init (struct DCC
*, struct session
*);
1363 dcc_connect (struct DCC
*dcc
)
1368 if (dcc
->dccstat
== STAT_CONNECTING
)
1370 dcc
->dccstat
= STAT_CONNECTING
;
1372 if (dcc
->pasvid
&& dcc
->port
== 0)
1374 /* accepted a passive dcc send */
1375 ret
= dcc_listen_init (dcc
, dcc
->serv
->front_session
);
1378 dcc_close (dcc
, STAT_FAILED
, FALSE
);
1381 /* possible problems with filenames containing spaces? */
1382 if (dcc
->type
== TYPE_RECV
)
1383 snprintf (tbuf
, sizeof (tbuf
), strchr (dcc
->file
, ' ') ?
1384 "DCC SEND \"%s\" %u %d %"DCC_SFMT
" %d" :
1385 "DCC SEND %s %u %d %"DCC_SFMT
" %d", dcc
->file
,
1386 dcc
->addr
, dcc
->port
, dcc
->size
, dcc
->pasvid
);
1388 snprintf (tbuf
, sizeof (tbuf
), "DCC CHAT chat %u %d %d",
1389 dcc
->addr
, dcc
->port
, dcc
->pasvid
);
1390 dcc
->serv
->p_ctcp (dcc
->serv
, dcc
->nick
, tbuf
);
1394 dcc
->sok
= dcc_connect_sok (dcc
);
1397 dcc
->dccstat
= STAT_FAILED
;
1398 fe_dcc_update (dcc
);
1401 if (DCC_USE_PROXY ())
1402 dcc
->iotag
= fe_input_add (dcc
->sok
, FIA_WRITE
|FIA_EX
, dcc_proxy_connect
, dcc
);
1404 dcc
->iotag
= fe_input_add (dcc
->sok
, FIA_WRITE
|FIA_EX
, dcc_connect_finished
, dcc
);
1407 fe_dcc_update (dcc
);
1411 dcc_send_data (GIOChannel
*source
, GIOCondition condition
, struct DCC
*dcc
)
1414 int len
, sent
, sok
= dcc
->sok
;
1416 if (prefs
.dcc_blocksize
< 1) /* this is too little! */
1417 prefs
.dcc_blocksize
= 1024;
1419 if (prefs
.dcc_blocksize
> 102400) /* this is too much! */
1420 prefs
.dcc_blocksize
= 102400;
1424 fe_input_remove (dcc
->wiotag
);
1431 if (dcc
->ack
< dcc
->pos
)
1434 else if (!dcc
->wiotag
)
1435 dcc
->wiotag
= fe_input_add (sok
, FIA_WRITE
, dcc_send_data
, dcc
);
1437 buf
= malloc (prefs
.dcc_blocksize
);
1441 lseek (dcc
->fp
, dcc
->pos
, SEEK_SET
);
1442 len
= read (dcc
->fp
, buf
, prefs
.dcc_blocksize
);
1445 sent
= send (sok
, buf
, len
, 0);
1447 if (sent
< 0 && !(would_block ()))
1451 EMIT_SIGNAL (XP_TE_DCCSENDFAIL
, dcc
->serv
->front_session
,
1452 file_part (dcc
->file
), dcc
->nick
,
1453 errorstring (sock_error ()), NULL
, 0);
1454 dcc_close (dcc
, STAT_FAILED
, FALSE
);
1460 dcc
->lasttime
= time (0);
1463 /* have we sent it all yet? */
1464 if (dcc
->pos
>= dcc
->size
)
1466 /* it's all sent now, so remove the WRITE/SEND handler */
1469 fe_input_remove (dcc
->wiotag
);
1480 dcc_handle_new_ack (struct DCC
*dcc
)
1484 gboolean done
= FALSE
;
1486 memcpy (&ack
, dcc
->ack_buf
, 4);
1487 dcc
->ack
= ntohl (ack
);
1489 /* this could mess up when xfering >32bit files */
1490 if (dcc
->size
<= 0xffffffff)
1492 /* fix for BitchX */
1493 if (dcc
->ack
< dcc
->resumable
)
1494 dcc
->ackoffset
= TRUE
;
1496 dcc
->ack
+= dcc
->resumable
;
1499 /* DCC complete check */
1500 if (dcc
->pos
>= dcc
->size
&& dcc
->ack
>= (dcc
->size
& 0xffffffff))
1502 dcc
->ack
= dcc
->size
; /* force 100% ack for >4 GB */
1503 dcc_close (dcc
, STAT_DONE
, FALSE
);
1504 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 */
1505 sprintf (buf
, "%d", dcc
->cps
);
1506 EMIT_SIGNAL (XP_TE_DCCSENDCOMP
, dcc
->serv
->front_session
,
1507 file_part (dcc
->file
), dcc
->nick
, buf
, NULL
, 0);
1510 else if ((!dcc
->fastsend
) && (dcc
->ack
>= (dcc
->pos
& 0xffffffff)))
1512 dcc_send_data (NULL
, 0, (gpointer
)dcc
);
1516 /* take the top 32 of "bytes send" and bottom 32 of "ack" */
1517 dcc
->ack
= (dcc
->pos
& G_GINT64_CONSTANT (0xffffffff00000000)) |
1518 (dcc
->ack
& 0xffffffff);
1519 /* dcc->ack is only used for CPS and PERCENTAGE calcs from now on... */
1526 dcc_read_ack (GIOChannel
*source
, GIOCondition condition
, struct DCC
*dcc
)
1532 /* try to fill up 4 bytes */
1533 len
= recv (dcc
->sok
, dcc
->ack_buf
, 4 - dcc
->ack_pos
, 0);
1538 if (would_block ()) /* ok - keep waiting */
1541 EMIT_SIGNAL (XP_TE_DCCSENDFAIL
, dcc
->serv
->front_session
,
1542 file_part (dcc
->file
), dcc
->nick
,
1543 errorstring ((len
< 0) ? sock_error () : 0), NULL
, 0);
1544 dcc_close (dcc
, STAT_FAILED
, FALSE
);
1548 dcc
->ack_pos
+= len
;
1549 if (dcc
->ack_pos
>= 4)
1552 if (dcc_handle_new_ack (dcc
))
1555 /* loop again until would_block() returns true */
1560 dcc_accept (GIOChannel
*source
, GIOCondition condition
, struct DCC
*dcc
)
1563 struct sockaddr_in CAddr
;
1567 len
= sizeof (CAddr
);
1568 sok
= accept (dcc
->sok
, (struct sockaddr
*) &CAddr
, &len
);
1569 fe_input_remove (dcc
->iotag
);
1571 closesocket (dcc
->sok
);
1575 dcc_close (dcc
, STAT_FAILED
, FALSE
);
1578 set_nonblocking (sok
);
1580 dcc
->addr
= ntohl (CAddr
.sin_addr
.s_addr
);
1583 return dcc_connect_finished (NULL
, 0, dcc
);
1585 dcc
->dccstat
= STAT_ACTIVE
;
1586 dcc
->lasttime
= dcc
->starttime
= time (0);
1587 dcc
->fastsend
= prefs
.fastdccsend
;
1589 snprintf (host
, sizeof (host
), "%s:%d", net_ip (dcc
->addr
), dcc
->port
);
1595 dcc
->wiotag
= fe_input_add (sok
, FIA_WRITE
, dcc_send_data
, dcc
);
1596 dcc
->iotag
= fe_input_add (sok
, FIA_READ
|FIA_EX
, dcc_read_ack
, dcc
);
1597 dcc_send_data (NULL
, 0, (gpointer
)dcc
);
1598 EMIT_SIGNAL (XP_TE_DCCCONSEND
, dcc
->serv
->front_session
,
1599 dcc
->nick
, host
, dcc
->file
, NULL
, 0);
1603 dcc_open_query (dcc
->serv
, dcc
->nick
);
1604 dcc
->iotag
= fe_input_add (dcc
->sok
, FIA_READ
|FIA_EX
, dcc_read_chat
, dcc
);
1605 dcc
->dccchat
= malloc (sizeof (struct dcc_chat
));
1606 dcc
->dccchat
->pos
= 0;
1607 EMIT_SIGNAL (XP_TE_DCCCONCHAT
, dcc
->serv
->front_session
,
1608 dcc
->nick
, host
, NULL
, NULL
, 0);
1612 fe_dcc_update (dcc
);
1618 dcc_get_my_address (void) /* the address we'll tell the other person */
1620 struct hostent
*dns_query
;
1623 if (prefs
.ip_from_server
&& prefs
.dcc_ip
)
1624 addr
= prefs
.dcc_ip
;
1625 else if (prefs
.dcc_ip_str
[0])
1627 dns_query
= gethostbyname ((const char *) prefs
.dcc_ip_str
);
1629 if (dns_query
!= NULL
&&
1630 dns_query
->h_length
== 4 &&
1631 dns_query
->h_addr_list
[0] != NULL
)
1633 /*we're offered at least one IPv4 address: we take the first*/
1634 addr
= *((guint32
*) dns_query
->h_addr_list
[0]);
1642 dcc_listen_init (struct DCC
*dcc
, session
*sess
)
1645 struct sockaddr_in SAddr
;
1646 int i
, bindretval
= -1;
1649 dcc
->sok
= socket (AF_INET
, SOCK_STREAM
, 0);
1653 memset (&SAddr
, 0, sizeof (struct sockaddr_in
));
1655 len
= sizeof (SAddr
);
1656 getsockname (dcc
->serv
->sok
, (struct sockaddr
*) &SAddr
, &len
);
1658 SAddr
.sin_family
= AF_INET
;
1660 /*if local_ip is specified use that*/
1661 if (prefs
.local_ip
!= 0xffffffff)
1663 my_addr
= prefs
.local_ip
;
1664 SAddr
.sin_addr
.s_addr
= prefs
.local_ip
;
1666 /*otherwise use the default*/
1668 my_addr
= SAddr
.sin_addr
.s_addr
;
1670 /*if we have a valid portrange try to use that*/
1671 if (prefs
.first_dcc_send_port
> 0)
1675 while ((prefs
.last_dcc_send_port
> ntohs(SAddr
.sin_port
)) &&
1678 SAddr
.sin_port
= htons (prefs
.first_dcc_send_port
+ i
);
1680 /*printf("Trying to bind against port: %d\n",ntohs(SAddr.sin_port));*/
1681 bindretval
= bind (dcc
->sok
, (struct sockaddr
*) &SAddr
, sizeof (SAddr
));
1684 /* with a small port range, reUseAddr is needed */
1686 setsockopt (dcc
->sok
, SOL_SOCKET
, SO_REUSEADDR
, (char *) &len
, sizeof (len
));
1690 /* try random port */
1692 bindretval
= bind (dcc
->sok
, (struct sockaddr
*) &SAddr
, sizeof (SAddr
));
1695 if (bindretval
== -1)
1697 /* failed to bind */
1698 PrintText (sess
, "Failed to bind to any address or port.\n");
1702 len
= sizeof (SAddr
);
1703 getsockname (dcc
->sok
, (struct sockaddr
*) &SAddr
, &len
);
1705 dcc
->port
= ntohs (SAddr
.sin_port
);
1707 /*if we have a dcc_ip, we use that, so the remote client can connect*/
1708 /*else we try to take an address from dcc_ip_str*/
1709 /*if something goes wrong we tell the client to connect to our LAN ip*/
1710 dcc
->addr
= dcc_get_my_address ();
1712 /*if nothing else worked we use the address we bound to*/
1714 dcc
->addr
= my_addr
;
1716 dcc
->addr
= ntohl (dcc
->addr
);
1718 set_nonblocking (dcc
->sok
);
1719 listen (dcc
->sok
, 1);
1720 set_blocking (dcc
->sok
);
1722 dcc
->iotag
= fe_input_add (dcc
->sok
, FIA_READ
|FIA_EX
, dcc_accept
, dcc
);
1727 static struct session
*dccsess
;
1728 static char *dccto
; /* lame!! */
1729 static int dccmaxcps
;
1730 static int recursive
= FALSE
;
1733 dcc_send_wild (char *file
)
1735 dcc_send (dccsess
, dccto
, file
, dccmaxcps
, 0);
1739 dcc_send (struct session
*sess
, char *to
, char *file
, int maxcps
, int passive
)
1747 file
= expand_homedir (file
);
1749 if (!recursive
&& (strchr (file
, '*') || strchr (file
, '?')))
1753 char *path_fs
; /* local filesystem encoding */
1755 safe_strcpy (wild
, file_part (file
), sizeof (wild
));
1756 path_part (file
, path
, sizeof (path
));
1757 if (path
[0] != '/' || path
[1] != '\0')
1758 path
[strlen (path
) - 1] = 0; /* remove trailing slash */
1766 /* for_files() will use opendir, so we need local FS encoding */
1767 path_fs
= xchat_filename_from_utf8 (path
, -1, 0, 0, 0);
1771 for_files (path_fs
, wild
, dcc_send_wild
);
1783 dcc
->maxcps
= maxcps
;
1785 /* get the local filesystem encoding */
1786 file_fs
= xchat_filename_from_utf8 (file
, -1, 0, 0, 0);
1788 if (stat (file_fs
, &st
) != -1)
1792 if (sizeof (st
.st_size
) > 4 && st
.st_size
> 4294967295U)
1794 PrintText (sess
, "Cannot send files larger than 4 GB.\n");
1799 if (!(*file_part (file_fs
)) || S_ISDIR (st
.st_mode
) || st
.st_size
< 1)
1801 PrintText (sess
, "Cannot send directories or empty files.\n");
1805 dcc
->starttime
= dcc
->offertime
= time (0);
1806 dcc
->serv
= sess
->server
;
1807 dcc
->dccstat
= STAT_QUEUED
;
1808 dcc
->size
= st
.st_size
;
1809 dcc
->type
= TYPE_SEND
;
1810 dcc
->fp
= open (file_fs
, OFLAGS
| O_RDONLY
);
1814 if (passive
|| dcc_listen_init (dcc
, sess
))
1816 char havespaces
= 0;
1822 if (prefs
.dcc_send_fillspaces
)
1829 dcc
->nick
= strdup (to
);
1830 if (prefs
.autoopendccsendwindow
)
1832 if (fe_dcc_open_send_win (TRUE
)) /* already open? add */
1839 dcc
->pasvid
= new_id();
1840 snprintf (outbuf
, sizeof (outbuf
), (havespaces
) ?
1841 "DCC SEND \"%s\" 199 0 %"DCC_SFMT
" %d" :
1842 "DCC SEND %s 199 0 %"DCC_SFMT
" %d",
1843 file_part (dcc
->file
),
1844 dcc
->size
, dcc
->pasvid
);
1847 snprintf (outbuf
, sizeof (outbuf
), (havespaces
) ?
1848 "DCC SEND \"%s\" %u %d %"DCC_SFMT
:
1849 "DCC SEND %s %u %d %"DCC_SFMT
,
1850 file_part (dcc
->file
), dcc
->addr
,
1851 dcc
->port
, dcc
->size
);
1853 sess
->server
->p_ctcp (sess
->server
, to
, outbuf
);
1855 EMIT_SIGNAL (XP_TE_DCCOFFER
, sess
, file_part (dcc
->file
),
1856 to
, dcc
->file
, NULL
, 0);
1859 dcc_close (dcc
, 0, TRUE
);
1864 PrintTextf (sess
, _("Cannot access %s\n"), dcc
->file
);
1865 PrintTextf (sess
, "%s %d: %s\n", _("Error"), errno
, errorstring (errno
));
1868 dcc_close (dcc
, 0, TRUE
);
1872 find_dcc_from_id (int id
, int type
)
1875 GSList
*list
= dcc_list
;
1878 dcc
= (struct DCC
*) list
->data
;
1879 if (dcc
->pasvid
== id
&&
1880 dcc
->dccstat
== STAT_QUEUED
&& dcc
->type
== type
)
1888 find_dcc_from_port (int port
, int type
)
1891 GSList
*list
= dcc_list
;
1894 dcc
= (struct DCC
*) list
->data
;
1895 if (dcc
->port
== port
&&
1896 dcc
->dccstat
== STAT_QUEUED
&& dcc
->type
== type
)
1904 find_dcc (char *nick
, char *file
, int type
)
1906 GSList
*list
= dcc_list
;
1910 dcc
= (struct DCC
*) list
->data
;
1911 if (nick
== NULL
|| !rfc_casecmp (nick
, dcc
->nick
))
1913 if (type
== -1 || dcc
->type
== type
)
1917 if (!strcasecmp (file
, file_part (dcc
->file
)))
1919 if (!strcasecmp (file
, dcc
->file
))
1928 /* called when we receive a NICK change from server */
1931 dcc_change_nick (struct server
*serv
, char *oldnick
, char *newnick
)
1934 GSList
*list
= dcc_list
;
1938 dcc
= (struct DCC
*) list
->data
;
1939 if (dcc
->serv
== serv
)
1941 if (!serv
->p_cmp (dcc
->nick
, oldnick
))
1945 dcc
->nick
= strdup (newnick
);
1952 /* is the destination file the same? new_dcc is not opened yet */
1955 is_same_file (struct DCC
*dcc
, struct DCC
*new_dcc
)
1957 struct stat st_a
, st_b
;
1959 /* if it's the same filename, must be same */
1960 if (strcmp (dcc
->destfile
, new_dcc
->destfile
) == 0)
1963 /* now handle case-insensitive Filesystems: HFS+, FAT */
1964 /* this fstat() shouldn't really fail */
1965 if ((dcc
->fp
== -1 ? stat (dcc
->destfile_fs
, &st_a
) : fstat (dcc
->fp
, &st_a
)) == -1)
1967 if (stat (new_dcc
->destfile_fs
, &st_b
) == -1)
1970 /* same inode, same device, same file! */
1971 if (st_a
.st_ino
== st_b
.st_ino
&&
1972 st_a
.st_dev
== st_b
.st_dev
)
1979 is_resumable (struct DCC
*dcc
)
1983 /* Check the file size */
1984 if (access (dcc
->destfile_fs
, W_OK
) == 0)
1988 if (stat (dcc
->destfile_fs
, &st
) != -1)
1990 if (st
.st_size
< dcc
->size
)
1992 dcc
->resumable
= st
.st_size
;
1993 dcc
->pos
= st
.st_size
;
1996 dcc
->resume_error
= 2;
1999 dcc
->resume_errno
= errno
;
2000 dcc
->resume_error
= 1;
2004 dcc
->resume_errno
= errno
;
2005 dcc
->resume_error
= 1;
2008 /* Now verify that this DCC is not already in progress from someone else */
2012 GSList
*list
= dcc_list
;
2017 if (d
->type
== TYPE_RECV
&& d
->dccstat
!= STAT_ABORTED
&&
2018 d
->dccstat
!= STAT_DONE
&& d
->dccstat
!= STAT_FAILED
)
2020 if (d
!= dcc
&& is_same_file (d
, dcc
))
2022 dcc
->resume_error
= 3; /* dccgui.c uses it */
2032 return dcc
->resumable
;
2036 dcc_get (struct DCC
*dcc
)
2038 switch (dcc
->dccstat
)
2041 if (dcc
->type
!= TYPE_CHATSEND
)
2043 if (dcc
->type
== TYPE_RECV
&& prefs
.autoresume
&& dcc
->resumable
)
2058 dcc_close (dcc
, 0, TRUE
);
2063 /* for "Save As..." dialog */
2066 dcc_get_with_destfile (struct DCC
*dcc
, char *file
)
2068 g_free (dcc
->destfile
);
2069 dcc
->destfile
= g_strdup (file
); /* utf-8 */
2071 /* get the local filesystem encoding */
2072 g_free (dcc
->destfile_fs
);
2073 dcc
->destfile_fs
= xchat_filename_from_utf8 (dcc
->destfile
, -1, 0, 0, 0);
2075 /* since destfile changed, must check resumability again */
2082 dcc_get_nick (struct session
*sess
, char *nick
)
2085 GSList
*list
= dcc_list
;
2088 dcc
= (struct DCC
*) list
->data
;
2089 if (!sess
->server
->p_cmp (nick
, dcc
->nick
))
2091 if (dcc
->dccstat
== STAT_QUEUED
&& dcc
->type
== TYPE_RECV
)
2103 EMIT_SIGNAL (XP_TE_DCCIVAL
, sess
, NULL
, NULL
, NULL
, NULL
, 0);
2109 struct DCC
*dcc
= malloc (sizeof (struct DCC
));
2112 memset (dcc
, 0, sizeof (struct DCC
));
2115 dcc_list
= g_slist_prepend (dcc_list
, dcc
);
2120 dcc_chat (struct session
*sess
, char *nick
, int passive
)
2125 dcc
= find_dcc (nick
, "", TYPE_CHATSEND
);
2128 switch (dcc
->dccstat
)
2132 case STAT_CONNECTING
:
2133 EMIT_SIGNAL (XP_TE_DCCCHATREOFFER
, sess
, nick
, NULL
, NULL
, NULL
, 0);
2137 dcc_close (dcc
, 0, TRUE
);
2140 dcc
= find_dcc (nick
, "", TYPE_CHATRECV
);
2143 switch (dcc
->dccstat
)
2150 dcc_close (dcc
, 0, TRUE
);
2154 /* offer DCC CHAT */
2159 dcc
->starttime
= dcc
->offertime
= time (0);
2160 dcc
->serv
= sess
->server
;
2161 dcc
->dccstat
= STAT_QUEUED
;
2162 dcc
->type
= TYPE_CHATSEND
;
2163 dcc
->nick
= strdup (nick
);
2164 if (passive
|| dcc_listen_init (dcc
, sess
))
2166 if (prefs
.autoopendccchatwindow
)
2168 if (fe_dcc_open_chat_win (TRUE
)) /* already open? add only */
2175 dcc
->pasvid
= new_id ();
2176 snprintf (outbuf
, sizeof (outbuf
), "DCC CHAT chat 199 %d %d",
2177 dcc
->port
, dcc
->pasvid
);
2180 snprintf (outbuf
, sizeof (outbuf
), "DCC CHAT chat %u %d",
2181 dcc
->addr
, dcc
->port
);
2183 dcc
->serv
->p_ctcp (dcc
->serv
, nick
, outbuf
);
2184 EMIT_SIGNAL (XP_TE_DCCCHATOFFERING
, sess
, nick
, NULL
, NULL
, NULL
, 0);
2187 dcc_close (dcc
, 0, TRUE
);
2192 dcc_malformed (struct session
*sess
, char *nick
, char *data
)
2194 EMIT_SIGNAL (XP_TE_MALFORMED
, sess
, nick
, data
, NULL
, NULL
, 0);
2198 dcc_resume (struct DCC
*dcc
)
2202 if (dcc
->dccstat
== STAT_QUEUED
&& dcc
->resumable
)
2204 dcc
->resume_sent
= 1;
2205 /* filename contains spaces? Quote them! */
2206 snprintf (tbuf
, sizeof (tbuf
) - 10, strchr (dcc
->file
, ' ') ?
2207 "DCC RESUME \"%s\" %d %"DCC_SFMT
:
2208 "DCC RESUME %s %d %"DCC_SFMT
,
2209 dcc
->file
, dcc
->port
, dcc
->resumable
);
2212 sprintf (tbuf
+ strlen (tbuf
), " %d", dcc
->pasvid
);
2214 dcc
->serv
->p_ctcp (dcc
->serv
, dcc
->nick
, tbuf
);
2222 dcc_confirm_send (void *ud
)
2224 struct DCC
*dcc
= (struct DCC
*) ud
;
2229 dcc_deny_send (void *ud
)
2231 struct DCC
*dcc
= (struct DCC
*) ud
;
2232 dcc_abort (dcc
->serv
->front_session
, dcc
);
2236 dcc_confirm_chat (void *ud
)
2238 struct DCC
*dcc
= (struct DCC
*) ud
;
2243 dcc_deny_chat (void *ud
)
2245 struct DCC
*dcc
= (struct DCC
*) ud
;
2246 dcc_abort (dcc
->serv
->front_session
, dcc
);
2250 dcc_add_chat (session
*sess
, char *nick
, int port
, guint32 addr
, int pasvid
)
2257 dcc
->serv
= sess
->server
;
2258 dcc
->type
= TYPE_CHATRECV
;
2259 dcc
->dccstat
= STAT_QUEUED
;
2262 dcc
->pasvid
= pasvid
;
2263 dcc
->nick
= strdup (nick
);
2264 dcc
->starttime
= time (0);
2266 EMIT_SIGNAL (XP_TE_DCCCHATOFFER
, sess
->server
->front_session
, nick
,
2267 NULL
, NULL
, NULL
, 0);
2269 if (prefs
.autoopendccchatwindow
)
2271 if (fe_dcc_open_chat_win (TRUE
)) /* already open? add only */
2276 if (prefs
.autodccchat
== 1)
2278 else if (prefs
.autodccchat
== 2)
2281 snprintf (buff
, sizeof (buff
), "%s is offering DCC Chat. Do you want to accept?", nick
);
2282 fe_confirm (buff
, dcc_confirm_chat
, dcc_deny_chat
, dcc
);
2290 dcc_add_file (session
*sess
, char *file
, DCC_SIZE size
, int port
, char *nick
, guint32 addr
, int pasvid
)
2298 dcc
->file
= strdup (file
);
2300 dcc
->destfile
= g_malloc (strlen (prefs
.dccdir
) + strlen (nick
) +
2303 strcpy (dcc
->destfile
, prefs
.dccdir
);
2304 if (prefs
.dccdir
[strlen (prefs
.dccdir
) - 1] != '/')
2305 strcat (dcc
->destfile
, "/");
2306 if (prefs
.dccwithnick
)
2308 strcat (dcc
->destfile
, nick
);
2309 strcat (dcc
->destfile
, ".");
2311 strcat (dcc
->destfile
, file
);
2313 /* get the local filesystem encoding */
2314 dcc
->destfile_fs
= xchat_filename_from_utf8 (dcc
->destfile
, -1, 0, 0, 0);
2318 dcc
->serv
= sess
->server
;
2319 dcc
->type
= TYPE_RECV
;
2320 dcc
->dccstat
= STAT_QUEUED
;
2323 dcc
->pasvid
= pasvid
;
2325 dcc
->nick
= strdup (nick
);
2326 dcc
->maxcps
= prefs
.dcc_max_get_cps
;
2330 /* autodccsend is really autodccrecv.. right? */
2332 if (prefs
.autodccsend
== 1)
2336 else if (prefs
.autodccsend
== 2)
2338 snprintf (tbuf
, sizeof (tbuf
), _("%s is offering \"%s\". Do you want to accept?"), nick
, file
);
2339 fe_confirm (tbuf
, dcc_confirm_send
, dcc_deny_send
, dcc
);
2341 if (prefs
.autoopendccrecvwindow
)
2343 if (fe_dcc_open_recv_win (TRUE
)) /* was already open? just add*/
2348 sprintf (tbuf
, "%"DCC_SFMT
, size
);
2349 snprintf (tbuf
+ 24, 300, "%s:%d", net_ip (addr
), port
);
2350 EMIT_SIGNAL (XP_TE_DCCSENDOFFER
, sess
->server
->front_session
, nick
,
2351 file
, tbuf
, tbuf
+ 24, 0);
2357 handle_dcc (struct session
*sess
, char *nick
, char *word
[],
2362 char *type
= word
[5];
2363 int port
, pasvid
= 0;
2368 if (!strcasecmp (type
, "CHAT"))
2370 port
= atoi (word
[8]);
2371 addr
= strtoul (word
[7], NULL
, 10);
2374 pasvid
= atoi (word
[9]);
2375 else if (word
[9][0] != 0)
2377 pasvid
= atoi (word
[9]);
2381 if (!addr
/*|| (port < 1024 && port != 0)*/
2382 || port
> 0xffff || (port
== 0 && pasvid
== 0))
2384 dcc_malformed (sess
, nick
, word_eol
[4] + 2);
2390 dcc
= find_dcc_from_id (pasvid
, TYPE_CHATSEND
);
2398 dcc_malformed (sess
, nick
, word_eol
[4] + 2);
2403 dcc
= find_dcc (nick
, "", TYPE_CHATSEND
);
2405 dcc_close (dcc
, 0, TRUE
);
2407 dcc
= find_dcc (nick
, "", TYPE_CHATRECV
);
2409 dcc_close (dcc
, 0, TRUE
);
2411 dcc_add_chat (sess
, nick
, port
, addr
, pasvid
);
2415 if (!strcasecmp (type
, "Resume"))
2417 port
= atoi (word
[7]);
2421 pasvid
= atoi(word
[9]);
2422 dcc
= find_dcc_from_id(pasvid
, TYPE_SEND
);
2425 dcc
= find_dcc_from_port (port
, TYPE_SEND
);
2428 dcc
= find_dcc (nick
, word
[6], TYPE_SEND
);
2431 size
= BIG_STR_TO_INT (word
[8]);
2432 dcc
->resumable
= size
;
2433 if (dcc
->resumable
< dcc
->size
)
2435 dcc
->pos
= dcc
->resumable
;
2436 dcc
->ack
= dcc
->resumable
;
2437 lseek (dcc
->fp
, dcc
->pos
, SEEK_SET
);
2439 /* Checking if dcc is passive and if filename contains spaces */
2441 snprintf (tbuf
, sizeof (tbuf
), strchr (file_part (dcc
->file
), ' ') ?
2442 "DCC ACCEPT \"%s\" %d %"DCC_SFMT
" %d" :
2443 "DCC ACCEPT %s %d %"DCC_SFMT
" %d",
2444 file_part (dcc
->file
), port
, dcc
->resumable
, dcc
->pasvid
);
2446 snprintf (tbuf
, sizeof (tbuf
), strchr (file_part (dcc
->file
), ' ') ?
2447 "DCC ACCEPT \"%s\" %d %"DCC_SFMT
:
2448 "DCC ACCEPT %s %d %"DCC_SFMT
,
2449 file_part (dcc
->file
), port
, dcc
->resumable
);
2451 dcc
->serv
->p_ctcp (dcc
->serv
, dcc
->nick
, tbuf
);
2453 sprintf (tbuf
, "%"DCC_SFMT
, dcc
->pos
);
2454 EMIT_SIGNAL (XP_TE_DCCRESUMEREQUEST
, sess
, nick
,
2455 file_part (dcc
->file
), tbuf
, NULL
, 0);
2459 if (!strcasecmp (type
, "Accept"))
2461 port
= atoi (word
[7]);
2462 dcc
= find_dcc_from_port (port
, TYPE_RECV
);
2463 if (dcc
&& dcc
->dccstat
== STAT_QUEUED
)
2469 if (!strcasecmp (type
, "SEND"))
2471 char *file
= file_part (word
[6]);
2473 port
= atoi (word
[8]);
2474 addr
= strtoul (word
[7], NULL
, 10);
2475 size
= BIG_STR_TO_INT (word
[9]);
2477 if (port
== 0) /* Passive dcc requested */
2478 pasvid
= atoi (word
[10]);
2479 else if (word
[10][0] != 0)
2481 /* Requesting passive dcc.
2482 * Destination user of an active dcc is giving his
2483 * TRUE address/port/pasvid data.
2484 * This information will be used later to
2485 * establish the connection to the user.
2486 * We can recognize this type of dcc using word[10]
2487 * because this field is always null (no pasvid)
2488 * in normal dcc sends.
2490 pasvid
= atoi (word
[10]);
2495 if (!addr
|| !size
/*|| (port < 1024 && port != 0)*/
2496 || port
> 0xffff || (port
== 0 && pasvid
== 0))
2498 dcc_malformed (sess
, nick
, word_eol
[4] + 2);
2504 /* Third Step of Passive send.
2505 * Connecting to the destination and finally
2508 dcc
= find_dcc_from_id (pasvid
, TYPE_SEND
);
2516 dcc_malformed (sess
, nick
, word_eol
[4] + 2);
2521 dcc_add_file (sess
, file
, size
, port
, nick
, addr
, pasvid
);
2525 EMIT_SIGNAL (XP_TE_DCCGENERICOFFER
, sess
->server
->front_session
,
2526 word_eol
[4] + 2, nick
, NULL
, NULL
, 0);
2531 dcc_show_list (struct session
*sess
)
2535 GSList
*list
= dcc_list
;
2537 EMIT_SIGNAL (XP_TE_DCCHEAD
, sess
, NULL
, NULL
, NULL
, NULL
, 0);
2540 dcc
= (struct DCC
*) list
->data
;
2542 PrintTextf (sess
, " %s %-10.10s %-7.7s %-7"DCC_SFMT
" %-7"DCC_SFMT
" %s\n",
2543 dcctypes
[dcc
->type
], dcc
->nick
,
2544 _(dccstat
[dcc
->dccstat
].name
), dcc
->size
, dcc
->pos
,
2545 file_part (dcc
->file
));
2549 PrintText (sess
, _("No active DCCs\n"));