Nie jestem na bieżąco z rozwojem EKG, więc zamiast commitować, podsyłam
skleconego naprędce patcha, który dodaje obsługę połączeń bezpośrednich
zgodnych z GG 7.x. Patch zakłada, że przy kompilacji jest brana libgadu
z systemu (wymagana wersja cvsowa), nie lokalnych źródeł. Możliwe, że
trzeba będzie dodać wykrywanie paru funkcji/stałych do configure,
możliwe, że trzeba będzie dać parę #ifdefów. SOA#1 ;)

w.
Index: src/Makefile.in
===================================================================
RCS file: /home/cvs/ekg/src/Makefile.in,v
retrieving revision 1.49
diff -u -r1.49 Makefile.in
--- src/Makefile.in	21 Mar 2007 04:51:07 -0000	1.49
+++ src/Makefile.in	3 Jun 2007 09:24:57 -0000
@@ -10,7 +10,7 @@
 sysconfdir = @sysconfdir@
 
 CC = @CC@ 
-CFLAGS = -I.. -I../lib @CFLAGS@ -DDATADIR=\"${datadir}/ekg\" -DSYSCONFDIR=\"${sysconfdir}\"
+CFLAGS = -I.. @CFLAGS@ -DDATADIR=\"${datadir}/ekg\" -DSYSCONFDIR=\"${sysconfdir}\"
 LDFLAGS = @LDFLAGS@
 LIBS = @LIBS@
 
@@ -28,7 +28,7 @@
 
 ekg:	$(OBJS) comptime.c @libgadu_a@
 	$(CC) $(CFLAGS) -c -o comptime.o comptime.c
-	$(CC) $(CFLAGS) -o ekg $(OBJS) comptime.o -L../lib @lgadu@ @libgadu_a@ $(LDFLAGS) $(LIBS)
+	$(CC) $(CFLAGS) -o ekg $(OBJS) comptime.o @lgadu@ @libgadu_a@ $(LDFLAGS) $(LIBS)
 
 ioctld:	ioctld.c
 	$(CC) $(CFLAGS) ioctld.c -o ioctld $(LIBS) @IOCTLD_OBJS@
Index: src/commands.c
===================================================================
RCS file: /home/cvs/ekg/src/commands.c,v
retrieving revision 1.775
diff -u -r1.775 commands.c
--- src/commands.c	27 Apr 2007 18:52:27 -0000	1.775
+++ src/commands.c	3 Jun 2007 09:24:58 -0000
@@ -2978,7 +2978,7 @@
 		for (l = transfers; l; l = l->next) {
 			struct transfer *t = l->data;
 
-			if (!t->dcc || !t->dcc->established) {
+			if ((!t->dcc && !t->dcc7) || (t->dcc && !t->dcc->established) || (t->dcc7 && !t->dcc7->established)) {
 				empty = 0;
 				if (!passed)
 					printq("dcc_show_pending_header");
@@ -2986,12 +2986,15 @@
 
 				switch (t->type) {
 					case GG_SESSION_DCC_SEND:
+					case GG_SESSION_DCC7_SEND:
 						printq("dcc_show_pending_send", itoa(t->id), format_user(t->uin), t->filename);
 						break;
 					case GG_SESSION_DCC_GET:
+					case GG_SESSION_DCC7_GET:
 						printq("dcc_show_pending_get", itoa(t->id), format_user(t->uin), t->filename);
 						break;
 					case GG_SESSION_DCC_VOICE:
+					case GG_SESSION_DCC7_VOICE:
 						printq("dcc_show_pending_voice", itoa(t->id), format_user(t->uin));
 				}
 			}
@@ -3002,8 +3005,22 @@
 		for (l = transfers; l; l = l->next) {
 			struct transfer *t = l->data;
 
-			if (t->dcc && t->dcc->established) {
+			if ((t->dcc && t->dcc->established) || (t->dcc7 && t->dcc7->established)) {
 				int eta_m = 0, eta_s = 0, speed_kb = 0;
+				unsigned int size = 0, offset = 0;
+
+				if (t->dcc) {
+					size = t->dcc->file_info.size;
+					offset = t->dcc->offset;
+				}
+
+				if (t->dcc7) {
+					size = t->dcc7->size;
+					offset = t->dcc7->offset;
+				}
+
+				if (!size)
+					size = 1;	// dzielimy przez size
 
 				empty = 0;
 				if (!passed)
@@ -3019,9 +3036,9 @@
 						elapsed = cur - t->start;
 
 					if (elapsed) {
-						speed = t->dcc->offset / elapsed;
-						if (t->dcc->offset && t->dcc->offset <= t->dcc->file_info.size)
-							eta = (t->dcc->file_info.size - t->dcc->offset) * elapsed / t->dcc->offset;
+						speed = offset / elapsed;
+						if (offset && offset <= size)
+							eta = (size - offset) * elapsed / offset;
 					}
 
 					/* teraz elapsed zawiera czas, który up³yn±³ 
@@ -3039,24 +3056,29 @@
 
 				switch (t->type) {
 					case GG_SESSION_DCC_SEND:
+					case GG_SESSION_DCC7_SEND:
 						if (speed_kb || eta_m || eta_s) {
 							if (eta_m)
-								printq("dcc_show_active_send_speed_ms", itoa(t->id), format_user(t->uin), t->filename, itoa(t->dcc->offset), itoa(t->dcc->file_info.size), itoa((float)100*((float)t->dcc->offset/(float)t->dcc->file_info.size)), itoa(speed_kb), itoa(eta_m), itoa(eta_s));
+								printq("dcc_show_active_send_speed_ms", itoa(t->id), format_user(t->uin), t->filename, itoa(offset), itoa(size), itoa((float)100*((float)offset/(float)size)), itoa(speed_kb), itoa(eta_m), itoa(eta_s));
 							else
-								printq("dcc_show_active_send_speed_s", itoa(t->id), format_user(t->uin), t->filename, itoa(t->dcc->offset), itoa(t->dcc->file_info.size), itoa((float)100*((float)t->dcc->offset/(float)t->dcc->file_info.size)), itoa(speed_kb), itoa(eta_s));
+								printq("dcc_show_active_send_speed_s", itoa(t->id), format_user(t->uin), t->filename, itoa(offset), itoa(size), itoa((float)100*((float)offset/(float)size)), itoa(speed_kb), itoa(eta_s));
 						} else
-							printq("dcc_show_active_send", itoa(t->id), format_user(t->uin), t->filename, itoa(t->dcc->offset), itoa(t->dcc->file_info.size), itoa((float)100*((float)t->dcc->offset/(float)t->dcc->file_info.size)));
+							printq("dcc_show_active_send", itoa(t->id), format_user(t->uin), t->filename, itoa(offset), itoa(size), itoa((float)100*((float)offset/(float)size)));
 						break;
+
 					case GG_SESSION_DCC_GET:
+					case GG_SESSION_DCC7_GET:
 						if (speed_kb || eta_m || eta_s) {
 							if (eta_m)
-								printq("dcc_show_active_get_speed_ms", itoa(t->id), format_user(t->uin), t->filename, itoa(t->dcc->offset), itoa(t->dcc->file_info.size), itoa((float)100*((float)t->dcc->offset/(float)t->dcc->file_info.size)), itoa(speed_kb), itoa(eta_m), itoa(eta_s));
+								printq("dcc_show_active_get_speed_ms", itoa(t->id), format_user(t->uin), t->filename, itoa(offset), itoa(size), itoa((float)100*((float)offset/(float)size)), itoa(speed_kb), itoa(eta_m), itoa(eta_s));
 							else
-								printq("dcc_show_active_get_speed_s", itoa(t->id), format_user(t->uin), t->filename, itoa(t->dcc->offset), itoa(t->dcc->file_info.size), itoa((float)100*((float)t->dcc->offset/(float)t->dcc->file_info.size)), itoa(speed_kb), itoa(eta_s));
+								printq("dcc_show_active_get_speed_s", itoa(t->id), format_user(t->uin), t->filename, itoa(offset), itoa(size), itoa((float)100*((float)offset/(float)size)), itoa(speed_kb), itoa(eta_s));
 						} else
-							printq("dcc_show_active_get", itoa(t->id), format_user(t->uin), t->filename, itoa(t->dcc->offset), itoa(t->dcc->file_info.size), itoa((float)100*((float)t->dcc->offset/(float)t->dcc->file_info.size)));
+							printq("dcc_show_active_get", itoa(t->id), format_user(t->uin), t->filename, itoa(offset), itoa(size), itoa((float)100*((float)offset/(float)size)));
 						break;
+
 					case GG_SESSION_DCC_VOICE:
+					case GG_SESSION_DCC7_VOICE:
 						printq("dcc_show_active_voice", itoa(t->id), format_user(t->uin));
 				}
 			}
@@ -3089,13 +3111,13 @@
 			printq("not_connected");
 			return -1;
 		}
-
+		
 		if (!(GG_S_A(u->status) || GG_S_B(u->status)) && !(ignored_check(uin) & IGNORE_STATUS)) {
 			printq("dcc_user_not_avail", format_user(u->uin), (u->first_name) ? u->first_name : u->display);
 			return -1;
 		}
 
-		if (!u->ip.s_addr && params[0][0] != 'r') {
+		if ((u->protocol < 0x2a && !u->ip.s_addr && params[0][0] != 'r') || (u->protocol >= 0x2a && !u->port)) {
 			printq("dcc_user_aint_dcc", format_user(u->uin));
 			return -1;
 		}
@@ -3122,33 +3144,50 @@
 		if (t.start == -1)
 			t.start = 0;
 
-		if (u->port < 10 || !strncasecmp(params[0], "rse", 3)) {
-			/* nie mo¿emy siê z nim po³±czyæ, wiêc on spróbuje */
-			gg_dcc_request(sess, uin);
+		if (u->protocol < 0x2a) {
+			if (u->port < 10 || !strncasecmp(params[0], "rse", 3)) {
+				/* nie mo¿emy siê z nim po³±czyæ, wiêc on spróbuje */
+				gg_dcc_request(sess, uin);
+			} else {
+				struct gg_dcc *d;
+				char *remote;
+				
+				if (!(d = gg_dcc_send_file(u->ip.s_addr, u->port, config_uin, uin))) {
+					printq("dcc_error", strerror(errno));
+					return -1;
+				}
+
+				remote = xstrdup(params[2]);
+				iso_to_cp((unsigned char *) remote);
+				
+				if (gg_dcc_fill_file_info2(d, remote, params[2]) == -1) {
+					printq("dcc_open_error", params[2], strerror(errno));
+					gg_free_dcc(d);
+					xfree(remote);
+					return -1;
+				}
+
+				xfree(remote);
+
+				list_add(&watches, d, 0);
+
+				t.dcc = d;
+			}
 		} else {
-			struct gg_dcc *d;
+			struct gg_dcc7 *d;
 			char *remote;
-			
-			if (!(d = gg_dcc_send_file(u->ip.s_addr, u->port, config_uin, uin))) {
-				printq("dcc_error", strerror(errno));
-				return -1;
-			}
 
-			remote = xstrdup(params[2]);
-			iso_to_cp((unsigned char *) remote);
-			
-			if (gg_dcc_fill_file_info2(d, remote, params[2]) == -1) {
-				printq("dcc_open_error", params[2], strerror(errno));
-				gg_free_dcc(d);
-				xfree(remote);
+			remote = xstrdup(t.filename);
+			iso_to_cp(remote);
+
+			if (!(d = gg_dcc7_send_file(sess, u->uin, t.filename, remote, NULL))) {
+				printq("dcc_error", strerror(errno));
 				return -1;
 			}
 
-			xfree(remote);
-
 			list_add(&watches, d, 0);
 
-			t.dcc = d;
+			t.dcc7 = d;
 		}
 
 		list_add(&transfers, &t, sizeof(t));
@@ -3280,16 +3319,27 @@
 	if (!strncasecmp(params[0], "g", 1) || !strncasecmp(params[0], "re", 2)) {		/* get */
 		struct transfer *t = NULL;
 		unsigned char *path, *tmp;
+		int fd;
+		unsigned int offset;
 		
 		for (l = transfers; l; l = l->next) {
 			struct transfer *tt = l->data;
 			struct userlist *u;
 
-			if (!tt->dcc || tt->type != GG_SESSION_DCC_GET || !tt->filename)
+			if (!tt->dcc && !tt->dcc7)
+				continue;
+
+			if (tt->dcc && tt->type != GG_SESSION_DCC_GET)
+				continue;
+
+			if (tt->dcc7 && tt->type != GG_SESSION_DCC7_GET)
+				continue;
+
+			if (!tt->filename)
 				continue;
 			
 			if (!params[1]) {
-				if (tt->dcc->established)
+				if ((tt->dcc && tt->dcc->established) || (tt->dcc7 && tt->dcc7->established))
 					continue;
 
 				t = tt;
@@ -3302,7 +3352,7 @@
 			}
 
 			if ((u = userlist_find(tt->uin, NULL))) {
-				if (tt->dcc->established)
+				if ((tt->dcc && tt->dcc->established) || (tt->dcc7 && tt->dcc7->established))
 					continue;
 
 				if (!strcasecmp(params[1], itoa(u->uin)) || (u->display && !strcasecmp(params[1], u->display))) {
@@ -3312,16 +3362,15 @@
 			}
 		}
 
-		if (!t || !t->dcc) {
+		if (!t || (!t->dcc && !t->dcc7)) {
 			printq("dcc_not_found", (params[1]) ? params[1] : "");
 			return -1;
 		}
 
 		for (l = watches; l; l = l->next) {
 			struct gg_common *c = l->data;
-			struct gg_dcc *d = l->data;
 
-			if (c->type == GG_SESSION_DCC_GET && t->dcc == d) {
+			if ((c->type == GG_SESSION_DCC_GET && t->dcc == l->data) || (c->type == GG_SESSION_DCC7_GET && t->dcc7 == l->data)) {
 				printq("dcc_receiving_already", t->filename, format_user(t->uin));
 				return -1;
 			}
@@ -3339,7 +3388,10 @@
 		tmp = unique_name(path);
 		if (!tmp) {
 			printq("dcc_get_cant_overwrite", path);
-			gg_free_dcc(t->dcc);
+			if (t->dcc)
+				gg_dcc_free(t->dcc);
+			if (t->dcc7)
+				gg_dcc7_free(t->dcc7);
 			list_remove(&transfers, t, 1);
 			xfree(path);
 			return -1;
@@ -3350,25 +3402,49 @@
 		}
 
 		if (params[0][0] == 'r') {
-			t->dcc->file_fd = open((char *) path, O_WRONLY);
-			t->dcc->offset = lseek(t->dcc->file_fd, 0, SEEK_END);
-		} else
-			t->dcc->file_fd = open((char *) path, O_WRONLY | O_CREAT, 0600);
+			fd = open((char *) path, O_WRONLY);
+			offset = lseek(fd, 0, SEEK_END);
+		} else {
+			fd = open((char *) path, O_WRONLY | O_CREAT, 0600);
+			offset = 0;
+		}
 
-		if (t->dcc->file_fd == -1) {
+		if (fd == -1) {
 			printq("dcc_get_cant_create", path);
-			gg_free_dcc(t->dcc);
+			if (t->dcc)
+				gg_dcc_free(t->dcc);
+			if (t->dcc7) {
+				gg_dcc7_reject(t->dcc7, GG_DCC7_REJECT_USER);
+				gg_dcc7_free(t->dcc7);
+			}
 			list_remove(&transfers, t, 1);
 			xfree(path);
 			
 			return -1;
 		}
+
+		if (t->dcc) {
+			t->dcc->file_fd = fd;
+			t->dcc->offset = offset;
+		}
+
+		if (t->dcc7) {
+			t->dcc7->file_fd = fd;
+			t->dcc7->offset = offset;
+			{ char buf[256]; sprintf(buf, "%p %d", t->dcc7, t->dcc7->file_fd); print("generic", buf); }
+		}
 		
 		xfree(path);
 		
 		printq("dcc_get_getting", format_user(t->uin), t->filename);
 		
-		list_add(&watches, t->dcc, 0);
+		if (t->dcc)
+			list_add(&watches, t->dcc, 0);
+			
+		if (t->dcc7) {
+			gg_dcc7_accept(t->dcc7, offset);
+			list_add(&watches, t->dcc7, 0);
+		}
 
 		return 0;
 	}
@@ -3403,13 +3479,20 @@
 			return -1;
 		}
 
+		if (t->dcc7) {
+			if (!t->dcc7->established)
+				gg_dcc7_reject(t->dcc7, GG_DCC7_REJECT_USER);
+			list_remove(&watches, t->dcc7, 0);
+			gg_dcc7_free(t->dcc7);
+		}
+
 		if (t->dcc) {
 			list_remove(&watches, t->dcc, 0);
 			gg_dcc_free(t->dcc);
 		}
 
 #ifdef HAVE_VOIP
-		if (t->type == GG_SESSION_DCC_VOICE)
+		if (t->type == GG_SESSION_DCC_VOICE || t->type == GG_SESSION_DCC7_VOICE)
 			voice_close();
 #endif
 
Index: src/ekg.c
===================================================================
RCS file: /home/cvs/ekg/src/ekg.c,v
retrieving revision 1.352
diff -u -r1.352 ekg.c
--- src/ekg.c	27 Apr 2007 18:52:27 -0000	1.352
+++ src/ekg.c	3 Jun 2007 09:24:59 -0000
@@ -149,6 +149,10 @@
 	EKG_HANDLER(GG_SESSION_DCC_SEND, handle_dcc, gg_dcc_free)
 	EKG_HANDLER(GG_SESSION_DCC_GET, handle_dcc, gg_dcc_free)
 	EKG_HANDLER(GG_SESSION_DCC_VOICE, handle_dcc, gg_dcc_free)
+	EKG_HANDLER(GG_SESSION_DCC7_SOCKET, handle_dcc7, gg_dcc7_free)
+	EKG_HANDLER(GG_SESSION_DCC7_SEND, handle_dcc7, gg_dcc7_free)
+	EKG_HANDLER(GG_SESSION_DCC7_GET, handle_dcc7, gg_dcc7_free)
+	EKG_HANDLER(GG_SESSION_DCC7_VOICE, handle_dcc7, gg_dcc7_free)
 	EKG_HANDLER(GG_SESSION_REGISTER, handle_pubdir, gg_register_free)
 	EKG_HANDLER(GG_SESSION_UNREGISTER, handle_pubdir, gg_pubdir_free)
 	EKG_HANDLER(GG_SESSION_PASSWD, handle_pubdir, gg_change_passwd_free)
@@ -404,6 +408,7 @@
 			struct gg_common *c = l->data;
 			struct gg_http *h = l->data;
 			struct gg_dcc *d = l->data;
+			struct gg_dcc7 *d7 = l->data;
 			static time_t last_check = 0;
 
 			if (!c || c->timeout == -1 || time(NULL) == last_check)
@@ -498,6 +503,32 @@
 					gg_free_dcc(d);
 					break;
 				}
+
+				case GG_SESSION_DCC7_GET:
+				case GG_SESSION_DCC7_SEND:
+				{
+					struct in_addr addr;
+					unsigned short port = d7->remote_port;
+					char *tmp;
+			
+					addr.s_addr = d7->remote_addr;
+
+					if (d7->peer_uin) {
+						struct userlist *u = userlist_find(d7->peer_uin, NULL);
+						if (!addr.s_addr && u) {
+							addr.s_addr = u->ip.s_addr;
+							port = u->port;
+						}
+						tmp = saprintf("%s (%s:%d)", format_user(d7->peer_uin), inet_ntoa(addr), port);
+					} else 
+						tmp = saprintf("%s:%d", inet_ntoa(addr), port);
+					print("dcc_timeout", tmp);
+					xfree(tmp);
+					remove_transfer(d7);
+					list_remove(&watches, d7, 0);
+					gg_dcc7_free(d7);
+					break;
+				}
 			}
 
 			break;
@@ -1533,6 +1564,7 @@
 #endif
 
 	changed_dcc("dcc");
+	changed_dcc("dcc_ip");
 
 #ifdef WITH_PYTHON
 	python_autorun();
Index: src/events.c
===================================================================
RCS file: /home/cvs/ekg/src/events.c,v
retrieving revision 1.385
diff -u -r1.385 events.c
--- src/events.c	27 Apr 2007 18:52:28 -0000	1.385
+++ src/events.c	3 Jun 2007 09:24:59 -0000
@@ -71,7 +71,8 @@
 void handle_msg(), handle_ack(), handle_status(), handle_notify(),
 	handle_success(), handle_failure(), handle_search50(),
 	handle_change50(), handle_status60(), handle_notify60(),
-	handle_userlist(), handle_image_request(), handle_image_reply();
+	handle_userlist(), handle_image_request(), handle_image_reply(),
+	handle_dcc7_new(), handle_dcc7_accept(), handle_dcc7_reject();
 
 static int hide_notavail = 0;	/* czy ma ukrywaæ niedostêpnych -- tylko zaraz po po³±czeniu */
 
@@ -96,6 +97,9 @@
 	{ GG_EVENT_USERLIST, handle_userlist },
 	{ GG_EVENT_IMAGE_REQUEST, handle_image_request },
 	{ GG_EVENT_IMAGE_REPLY, handle_image_reply },
+	{ GG_EVENT_DCC7_NEW, handle_dcc7_new },
+	{ GG_EVENT_DCC7_ACCEPT, handle_dcc7_accept },
+	{ GG_EVENT_DCC7_REJECT, handle_dcc7_reject },
 	{ 0, NULL }
 };
 
@@ -2232,18 +2236,18 @@
  *
  * znajduje strukturê ,,transfer'' dotycz±c± danego po³±czenia.
  *
- *  - d - struktura gg_dcc, której szukamy.
+ *  - d - struktura gg_dcc lub gg_dcc7, której szukamy.
  *
  * wska¼nik do struktury ,,transfer'' lub NULL, je¶li nie znalaz³.
  */
-static struct transfer *find_transfer(struct gg_dcc *d)
+static struct transfer *find_transfer(void *d)
 {
 	list_t l;
 
 	for (l = transfers; l; l = l->next) {
 		struct transfer *t = l->data;
 
-		if (t->dcc == d)
+		if (t->dcc == d || t->dcc7 == d)
 			return t;
 	}
 
@@ -2259,7 +2263,7 @@
  *
  * nie zwraca nic.
  */
-void remove_transfer(struct gg_dcc *d)
+void remove_transfer(void *d)
 {
 	struct transfer *t = find_transfer(d);
 
@@ -2270,6 +2274,60 @@
 }
 
 /*
+ * check_dcc_limit()
+ *
+ * sprawdza czy nie przekroczono limitu po³±czeñ bezpo¶rednich. je¶li tak,
+ * wy³±cza je i zwalnia strukturê gg_dcc przekazan± w zdarzeniu.
+ *
+ *  - e - struktura zdarzenia.
+ *
+ * 0/-1.
+ */
+static int check_dcc_limit(struct gg_event *e)
+{
+	int c, t = 60;
+	char *tmp;
+
+	if (!config_dcc_limit)
+		return 0;
+
+	if ((tmp = strchr(config_dcc_limit, '/')))
+		t = atoi(tmp + 1);
+
+	c = atoi(config_dcc_limit);
+
+	if (time(NULL) - dcc_limit_time > t) {
+		dcc_limit_time = time(NULL);
+		dcc_limit_count = 0;
+	}
+
+	dcc_limit_count++;
+
+	if (dcc_limit_count > c) {
+		print("dcc_limit");
+		config_dcc = 0;
+		changed_dcc("dcc");
+
+		dcc_limit_time = 0;
+		dcc_limit_count = 0;
+
+		if (e->type == GG_EVENT_DCC_NEW) {
+			gg_dcc_free(e->event.dcc_new);
+			e->event.dcc_new = NULL;
+		}
+
+		if (e->type == GG_EVENT_DCC7_NEW) {
+			gg_dcc7_free(e->event.dcc7_new);
+			e->event.dcc7_new = NULL;
+		}
+
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
  * handle_dcc()
  *
  * funkcja zajmuje siê obs³ug± wszystkich zdarzeñ zwi±zanych z DCC.
@@ -2303,37 +2361,10 @@
 
 	switch (e->type) {
 		case GG_EVENT_DCC_NEW:
-			gg_debug(GG_DEBUG_MISC, "## GG_EVENT_DCC_CLIENT_NEW\n");
-
-			if (config_dcc_limit) {
-				int c, t = 60;
-				char *tmp;
-				
-				if ((tmp = strchr(config_dcc_limit, '/')))
-					t = atoi(tmp + 1);
-
-				c = atoi(config_dcc_limit);
-
-				if (time(NULL) - dcc_limit_time > t) {
-					dcc_limit_time = time(NULL);
-					dcc_limit_count = 0;
-				}
+			gg_debug(GG_DEBUG_MISC, "## GG_EVENT_DCC_NEW\n");
 
-				dcc_limit_count++;
-
-				if (dcc_limit_count > c) {
-					print("dcc_limit");
-					config_dcc = 0;
-					changed_dcc("dcc");
-
-					dcc_limit_time = 0;
-					dcc_limit_count = 0;
-
-					gg_dcc_free(e->event.dcc_new);
-					e->event.dcc_new = NULL;
-					break;
-				}
-			}
+			if (check_dcc_limit(e) == -1)
+				break;
 
 			list_add(&watches, e->event.dcc_new, 0);
 			e->event.dcc_new = NULL;
@@ -2578,6 +2609,236 @@
 }
 
 /*
+ * handle_dcc7()
+ *
+ * funkcja zajmuje siê obs³ug± zdarzeñ zwi±zanych z DCC 7.x.
+ *
+ *  - d - struktura danego po³±czenia.
+ *
+ * nie zwraca niczego.
+ */
+void handle_dcc7(struct gg_dcc7 *d)
+{
+	struct gg_event *e;
+	struct transfer *t;
+
+	if (ignored_check(d->peer_uin) & IGNORE_DCC) {
+		remove_transfer(d);
+		list_remove(&watches, d, 0);
+		gg_dcc7_free(d);
+		return;
+	}
+	
+	if (!(e = gg_dcc7_watch_fd(d))) {
+		print("dcc_error", strerror(errno));
+		if (d->type != GG_SESSION_DCC7_SOCKET) {
+			remove_transfer(d);
+			list_remove(&watches, d, 0);
+			gg_dcc7_free(d);
+		}
+		return;
+	}
+
+	switch (e->type) {
+#if 0
+		case GG_EVENT_DCC_CLIENT_ACCEPT:
+		{
+			struct userlist *u;
+			
+			gg_debug(GG_DEBUG_MISC, "## GG_EVENT_DCC_CLIENT_ACCEPT\n");
+			
+			if (!(u = userlist_find(d->peer_uin, NULL)) || config_uin != d->uin) {
+				gg_debug(GG_DEBUG_MISC, "## unauthorized client (uin=%ld), closing connection\n", d->peer_uin);
+				list_remove(&watches, d, 0);
+				gg_free_dcc(d);
+				return;
+			}
+
+			if (config_dcc_filter && d->remote_addr != u->ip.s_addr) {
+				char tmp[20];
+
+				snprintf(tmp, sizeof(tmp), "%s", inet_ntoa(*((struct in_addr*) &d->remote_addr)));
+				
+				print("dcc_spoof", format_user(d->peer_uin), inet_ntoa(u->ip), tmp);
+			}
+
+			t = find_transfer(d);
+			if (t) {
+				t->start = time(NULL);
+				if (t->start == -1)
+					t->start = 0;
+			}
+
+			break;
+		}
+
+		case GG_EVENT_DCC_CALLBACK:
+		{
+			int found = 0;
+			
+			gg_debug(GG_DEBUG_MISC, "## GG_EVENT_DCC_CALLBACK\n");
+			
+			for (l = transfers; l; l = l->next) {
+				struct transfer *t = l->data;
+
+				gg_debug(GG_DEBUG_MISC, "// transfer id=%d, uin=%d, type=%d\n", t->id, t->uin, t->type);
+
+				if (t->uin == d->peer_uin && !t->dcc) {
+					gg_debug(GG_DEBUG_MISC, "## found transfer, uin=%d, type=%d\n", d->peer_uin, t->type);
+					t->dcc = d;
+					gg_dcc_set_type(d, t->type);
+					found = 1;
+					break;
+				}
+			}
+			
+			if (!found) {
+				gg_debug(GG_DEBUG_MISC, "## connection from %d not found\n", d->peer_uin);
+				list_remove(&watches, d, 0);
+				gg_dcc_free(d);
+			}
+			
+			break;	
+		}
+
+		case GG_EVENT_DCC_NEED_FILE_INFO:
+			gg_debug(GG_DEBUG_MISC, "## GG_EVENT_DCC_NEED_FILE_INFO\n");
+
+			for (l = transfers; l; l = l->next) {
+				struct transfer *t = l->data;
+
+				if (t->dcc == d) {
+					char *remote;
+
+					remote = xstrdup(t->filename);
+					iso_to_cp(remote);
+
+					if (gg_dcc_fill_file_info2(d, remote, t->filename) == -1) {
+						gg_debug(GG_DEBUG_MISC, "## gg_dcc_fill_file_info() failed (%s)\n", strerror(errno));
+						print("dcc_open_error", t->filename);
+						remove_transfer(d);
+						list_remove(&watches, d, 0);
+						gg_free_dcc(d);
+						xfree(remote);
+						break;
+					}
+
+					xfree(remote);
+					
+					break;
+				}
+			}
+			break;
+			
+		case GG_EVENT_DCC_NEED_VOICE_ACK:
+			gg_debug(GG_DEBUG_MISC, "## GG_EVENT_DCC_NEED_VOICE_ACK\n");
+#ifdef HAVE_VOIP
+			/* ¿eby nie sprawdza³o, póki luser nie odpowie */
+			list_remove(&watches, d, 0);
+
+			if (!(t = find_transfer(d))) {
+				tt.uin = d->peer_uin;
+				tt.type = GG_SESSION_DCC_VOICE;
+				tt.filename = NULL;
+				tt.dcc = d;
+				tt.id = transfer_id();
+				if (!(t = list_add(&transfers, &tt, sizeof(tt)))) {
+					gg_free_dcc(d);
+					break;
+				}
+			}
+			
+			t->type = GG_SESSION_DCC_VOICE;
+
+			print("dcc_voice_offer", format_user(t->uin), itoa(t->id));
+#else
+			list_remove(&watches, d, 0);
+			remove_transfer(d);
+			gg_free_dcc(d);
+#endif
+			break;
+
+		case GG_EVENT_DCC_VOICE_DATA:
+			gg_debug(GG_DEBUG_MISC, "## GG_EVENT_DCC_VOICE_DATA\n");
+
+#ifdef HAVE_VOIP
+			voice_open();
+			voice_play(e->event.dcc_voice_data.data, e->event.dcc_voice_data.length, 0);
+#endif
+			break;
+	
+#endif
+		case GG_EVENT_DCC7_DONE:
+			gg_debug(GG_DEBUG_MISC, "## GG_EVENT_DCC7_DONE\n");
+
+			if (!(t = find_transfer(d))) {
+				gg_dcc7_free(d);
+				break;
+			}
+
+			event_check(EVENT_DCCFINISH, t->uin, t->filename);
+
+			print((t->dcc7->type == GG_SESSION_DCC7_SEND) ? "dcc_done_send" : "dcc_done_get", format_user(t->uin), t->filename);
+			
+			remove_transfer(d);
+			list_remove(&watches, d, 0);
+			gg_dcc7_free(d);
+
+			break;
+			
+		case GG_EVENT_DCC7_ERROR:
+		{
+			struct in_addr addr;
+			unsigned short port = d->remote_port;
+			char *tmp;
+		
+			addr.s_addr = d->remote_addr;
+
+			if (d->peer_uin) {
+				struct userlist *u = userlist_find(d->peer_uin, NULL);
+				if (!addr.s_addr && u) {
+					addr.s_addr = u->ip.s_addr;
+					port = u->port;
+				}
+				tmp = saprintf("%s (%s:%d)", format_user(d->peer_uin), inet_ntoa(addr), port);
+			} else 
+				tmp = saprintf("%s:%d", inet_ntoa(addr), port);
+			
+			switch (e->event.dcc7_error) {
+				case GG_ERROR_DCC7_HANDSHAKE:
+					print("dcc_error_handshake", tmp);
+					break;
+				case GG_ERROR_DCC7_NET:
+					print("dcc_error_network", tmp);
+					break;
+				case GG_ERROR_DCC7_REFUSED:
+					print("dcc_error_refused", tmp);
+					break;
+				default:
+					print("dcc_error_unknown", tmp);
+			}
+
+			xfree(tmp);
+
+#ifdef HAVE_VOIP
+			if (d->type == GG_SESSION_DCC7_VOICE)
+				voice_close();
+#endif  /* HAVE_VOIP */
+
+			remove_transfer(d);
+			list_remove(&watches, d, 0);
+			gg_dcc7_free(d);
+
+			break;
+		}
+	}
+
+	gg_event_free(e);
+	
+	return;
+}
+
+/*
  * handle_voice()
  *
  * obs³uga danych przychodz±cych z urz±dzenia wej¶ciowego.
@@ -2928,3 +3189,116 @@
 			print("user_is_connected", format_user(e->event.image_reply.sender), itoa(e->event.image_reply.sender)); 
 	}
 }
+
+/*
+ * handle_dcc7_new()
+ *
+ * obs³uguje nowe po³±czenie dcc.
+ * 
+ *  - e - opis zdarzenia
+ */
+void handle_dcc7_new(struct gg_event *e)
+{
+	struct gg_dcc7 *dcc = e->event.dcc7_new;
+	struct transfer t;
+
+	if (!config_dcc) {
+		gg_dcc7_reject(dcc, GG_DCC7_REJECT_USER);
+		gg_dcc7_free(dcc);
+		e->event.dcc7_new = NULL;
+		return;
+	}
+
+	if (check_dcc_limit(e) == -1)
+		return;
+
+	memset(&t, 0, sizeof(t));
+	t.id = transfer_id();
+	t.uin = dcc->peer_uin;
+	t.dcc7 = dcc;
+
+	switch (dcc->dcc_type) {
+		case GG_DCC7_TYPE_FILE:
+		{
+			struct stat st;
+			char *path;
+
+			t.type = GG_SESSION_DCC7_GET;
+			t.filename = xstrdup(dcc->filename);
+			cp_to_iso(t.filename);
+			fix_filename(t.filename);
+
+			print("dcc_get_offer", format_user(t.uin), t.filename, itoa(dcc->size), itoa(t.id));
+
+			if (config_dcc_dir)
+				path = saprintf("%s/%s", config_dcc_dir, t.filename);
+			else
+				path = xstrdup(t.filename);
+
+			if (!stat(path, &st) && st.st_size < dcc->size)
+				print("dcc_get_offer_resume", format_user(t.uin), t.filename, itoa(dcc->size), itoa(t.id));
+			
+			xfree(path);
+
+			break;
+		}
+
+		case GG_DCC7_TYPE_VOICE:
+#ifdef HAVE_VOIP
+			t.type = GG_SESSION_DCC7_VOICE;
+
+			print("dcc_voice_offer", format_user(t.uin), itoa(t.id));
+			break;
+#else
+			gg_dcc7_free(dcc);
+			e->event.dcc7_new = NULL;
+			return;
+#endif
+
+		default:
+			gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_dcc7_new() unknown type %d\n", dcc->type);
+
+	}
+
+	list_add(&transfers, &t, sizeof(t));
+
+	if (!(ignored_check(t.uin) & IGNORE_EVENTS))
+		event_check(EVENT_DCC, t.uin, t.filename);
+}
+
+/*
+ * handle_dcc7_accept()
+ *
+ * obs³uguje akceptacjê po³±czenia dcc.
+ * 
+ *  - e - opis zdarzenia
+ */
+void handle_dcc7_accept(struct gg_event *e)
+{
+
+
+}
+
+/*
+ * handle_dcc7_reject()
+ *
+ * obs³uguje odrzucenie po³±czenia dcc.
+ * 
+ *  - e - opis zdarzenia
+ */
+void handle_dcc7_reject(struct gg_event *e)
+{
+	struct gg_dcc7 *d = e->event.dcc7_accept.dcc7;
+
+	print("dcc_error_refused", format_user(d->peer_uin));
+
+#ifdef HAVE_VOIP
+	if (d->type == GG_SESSION_DCC7_VOICE)
+		voice_close();
+#endif  /* HAVE_VOIP */
+
+	remove_transfer(d);
+	list_remove(&watches, d, 0);
+	gg_dcc7_free(d);
+}
+
Index: src/events.h
===================================================================
RCS file: /home/cvs/ekg/src/events.h,v
retrieving revision 1.22
diff -u -r1.22 events.h
--- src/events.h	18 Feb 2005 14:06:17 -0000	1.22
+++ src/events.h	3 Jun 2007 09:24:59 -0000
@@ -1,4 +1,4 @@
-/* $Id: events.h,v 1.22 2005-02-18 14:06:17 szalik Exp $ */
+/* $Id: events.h,v 1.22 2005/02/18 14:06:17 szalik Exp $ */
 
 /*
  *  (C) Copyright 2001-2002 Wojtek Kaniewski <[EMAIL PROTECTED]>
@@ -31,6 +31,7 @@
 
 void handle_event(struct gg_session *s);
 void handle_dcc(struct gg_dcc *s);
+void handle_dcc7(struct gg_dcc7 *s);
 void handle_msg(struct gg_event *e);
 void handle_voice(struct gg_common *c);
 
@@ -41,7 +42,7 @@
 
 void print_message(struct gg_event *e, struct userlist *u, int chat, int secure);
 
-void remove_transfer(struct gg_dcc *d);
+void remove_transfer(void *d);
 
 void handle_common(uin_t uin, int status, const char *idescr, int dtime, uint32_t ip, uint16_t port, int version, int image_size);
 
Index: src/stuff.c
===================================================================
RCS file: /home/cvs/ekg/src/stuff.c,v
retrieving revision 1.462
diff -u -r1.462 stuff.c
--- src/stuff.c	27 Apr 2007 18:52:28 -0000	1.462
+++ src/stuff.c	3 Jun 2007 09:25:00 -0000
@@ -53,7 +53,7 @@
 #include <unistd.h>
 
 #include "commands.h"
-#include "compat.h"
+#include "../compat/sunos.h"
 #include "dynstuff.h"
 #include "libgadu.h"
 #ifdef HAVE_OPENSSL
Index: src/stuff.h
===================================================================
RCS file: /home/cvs/ekg/src/stuff.h,v
retrieving revision 1.288
diff -u -r1.288 stuff.h
--- src/stuff.h	27 Apr 2007 18:52:28 -0000	1.288
+++ src/stuff.h	3 Jun 2007 09:25:00 -0000
@@ -100,6 +100,7 @@
 	uin_t uin;
 	char *filename;
 	struct gg_dcc *dcc;
+	struct gg_dcc7 *dcc7;
 	time_t start;
 	int type;
 	int id;
Index: src/themes.c
===================================================================
RCS file: /home/cvs/ekg/src/themes.c,v
retrieving revision 1.349
diff -u -r1.349 themes.c
--- src/themes.c	8 May 2007 21:01:26 -0000	1.349
+++ src/themes.c	3 Jun 2007 09:25:01 -0000
@@ -1274,6 +1274,7 @@
 	format_add("dcc_spoof", "%! %|U¿ytkownik %1 poda³ serwerowi adres %T%2%n, ale po³±czy³ siê z nami z adresu %T%3%n. Mo¿liwe, ¿e kto¶ próbuje siê pod niego podszyæ. Zachowaj ostro¿no¶æ!\n", 1);
 	format_add("dcc_limit", "%! %|Przekroczono limit bezpo¶rednich po³±czeñ i dla bezpieczeñstwa zosta³y one wy³±czone. Aby je w³±czyæ ponownie, nale¿y wpisaæ polecenie %Tset dcc 1%n i po³±czyæ siê ponownie. Limit mo¿na zmieniæ za pomoc± zmiennej %Tdcc_limit%n.\n", 1);
 	format_add("dcc_create_error", "%! Nie mo¿na w³±czyæ po³±czeñ bezpo¶rednich: %1\n", 1);
+	format_add("dcc_error", "%! B³±d transmisji: %1\n", 1);
 	format_add("dcc_error_network", "%! B³±d transmisji z %1\n", 1);
 	format_add("dcc_error_refused", "%! Po³±czenie z %1 zosta³o odrzucone\n", 1);
 	format_add("dcc_error_unknown", "%! Nieznany b³±d po³±czenia bezpo¶redniego\n", 1);
_______________________________________________
libgadu-devel mailing list
libgadu-devel@lists.ziew.org
http://lists.ziew.org/mailman/listinfo/libgadu-devel

Reply via email to