changeset 2806:1ffac7cf4e94

[gaim-migrate @ 2819] thanks Arkadiusz Miskiewicz: Here is patch that adds ,,delete userlist from server'', updates protocol.txt and makes small cleanup with freeing webdata + with function names (all agg_ names are reserved for struct prpl functions ;) committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Tue, 27 Nov 2001 22:54:32 +0000
parents 9b3c7d2a6e9a
children f01e6a425136
files src/protocols/gg/gg.c src/protocols/gg/protocol.txt
diffstat 2 files changed, 151 insertions(+), 49 deletions(-) [+]
line wrap: on
line diff
--- a/src/protocols/gg/gg.c	Tue Nov 27 22:46:03 2001 +0000
+++ b/src/protocols/gg/gg.c	Tue Nov 27 22:54:32 2001 +0000
@@ -1,6 +1,6 @@
 /*
  * gaim - Gadu-Gadu Protocol Plugin
- * $Id: gg.c 2805 2001-11-26 21:22:56Z warmenhoven $
+ * $Id: gg.c 2819 2001-11-27 22:54:32Z warmenhoven $
  *
  * Copyright (C) 2001 Arkadiusz Miśkiewicz <misiek@pld.ORG.PL>
  * 
@@ -79,6 +79,7 @@
 #define AGG_HTTP_SEARCH			1
 #define AGG_HTTP_USERLIST_IMPORT	2
 #define AGG_HTTP_USERLIST_EXPORT	3
+#define AGG_HTTP_USERLIST_DELETE	4
 
 #define UC_NORMAL 2
 
@@ -578,7 +579,6 @@
 	gd->sess->state = GG_STATE_CONNECTING_HTTP;
 	gd->sess->check = GG_CHECK_WRITE;
 	gd->sess->async = 1;
-	gd->sess->recv_left = 0;
 	gd->sess->fd = proxy_connect(GG_APPMSG_HOST, GG_APPMSG_PORT, login_callback, gc);
 
 	if (gd->sess->fd < 0) {
@@ -667,7 +667,6 @@
 
 	if ((ptr = strstr(webdata, "query_results:")) == NULL || (ptr = strchr(ptr, '\n')) == NULL) {
 		debug_printf("search_callback: pubdir result [%s]\n", webdata);
-		g_free(webdata);
 		do_error_dialog(_("Couldn't get search results"), _("Gadu-Gadu Error"));
 		return;
 	}
@@ -677,8 +676,6 @@
 
 	webdata_tbl = g_strsplit(ptr, "\n", AGG_PUBDIR_MAX_ENTRIES);
 
-	g_free(webdata);
-
 	j = 0;
 
 	/* Parse array */
@@ -768,28 +765,25 @@
 	g_free(buf);
 }
 
-static void agg_import_buddies_results(struct gaim_connection *gc, gchar *webdata)
+static void import_buddies_server_results(struct gaim_connection *gc, gchar *webdata)
 {
 	gchar *ptr;
 	gchar **users_tbl;
 	int i;
 	if (strstr(webdata, "no_data:")) {
-		g_free(webdata);
 		do_error_dialog(_("There is no Buddy List stored on server. Sorry!"),
 				_("Gadu-Gadu Error"));
 		return;
 	}
 
 	if ((ptr = strstr(webdata, "get_results:")) == NULL || (ptr = strchr(ptr, ':')) == NULL) {
-		debug_printf("agg_import_buddies_list: import buddies result [%s]\n", webdata);
-		g_free(webdata);
+		debug_printf("import_buddies_server_results: import buddies result [%s]\n", webdata);
 		do_error_dialog(_("Couldn't Import Buddies List from Server"), _("Gadu-Gadu Error"));
 		return;
 	}
 	ptr++;
 
 	users_tbl = g_strsplit(ptr, "\n", AGG_PUBDIR_MAX_ENTRIES);
-	g_free(webdata);
 
 	/* Parse array of Buddies List */
 	for (i = 0; users_tbl[i] != NULL; i++) {
@@ -806,7 +800,7 @@
 			continue;
 		}
 
-		debug_printf("uin: %s\n", name);
+		debug_printf("import_buddies_server_results: uin: %s\n", name);
 		if (!find_buddy(gc, name)) {
 			/* Default group if none specified on server */
 			gchar *group = g_strdup("Gadu-Gadu");
@@ -828,20 +822,30 @@
 	g_strfreev(users_tbl);
 }
 
-static void agg_export_buddies_results(struct gaim_connection *gc, gchar *webdata)
+static void export_buddies_server_results(struct gaim_connection *gc, gchar *webdata)
 {
 	if (strstr(webdata, "put_success:")) {
-		g_free(webdata);
 		do_error_dialog(_("Buddies List sucessfully transfered into Server"),
 				_("Gadu-Gadu Information"));
 		return;
 	}
 
-	debug_printf("agg_export_buddies_results: webdata [%s]\n", webdata);
-	g_free(webdata);
+	debug_printf("export_buddies_server_results: webdata [%s]\n", webdata);
 	do_error_dialog(_("Couldn't transfer Buddies List into Server"), _("Gadu-Gadu Error"));
 }
 
+static void delete_buddies_server_results(struct gaim_connection *gc, gchar *webdata)
+{
+	if (strstr(webdata, "put_success:")) {
+		do_error_dialog(_("Buddies List sucessfully deleted from Server"),
+				_("Gadu-Gadu Information"));
+		return;
+	}
+
+	debug_printf("delete_buddies_server_results: webdata [%s]\n", webdata);
+	do_error_dialog(_("Couldn't delete Buddies List from Server"), _("Gadu-Gadu Error"));
+}
+
 static void http_results(gpointer data, gint source, GaimInputCondition cond)
 {
 	struct agg_http *hdata = data;
@@ -890,10 +894,13 @@
 		search_results(gc, webdata);
 		break;
 	case AGG_HTTP_USERLIST_IMPORT:
-		agg_import_buddies_results(gc, webdata);
+		import_buddies_server_results(gc, webdata);
 		break;
 	case AGG_HTTP_USERLIST_EXPORT:
-		agg_export_buddies_results(gc, webdata);
+		export_buddies_server_results(gc, webdata);
+		break;
+	case AGG_HTTP_USERLIST_DELETE:
+	        delete_buddies_server_results(gc, webdata);
 		break;
 	case AGG_HTTP_NONE:
 	default:
@@ -901,6 +908,7 @@
 		break;
 	}
 
+	g_free(webdata);
 	g_free(hdata);
 }
 
@@ -956,7 +964,7 @@
 	hdata->inpa = gaim_input_add(source, GAIM_INPUT_READ, http_results, hdata);
 }
 
-static void agg_import_buddies(struct gaim_connection *gc)
+static void import_buddies_server(struct gaim_connection *gc)
 {
 	struct agg_http *hi = g_new0(struct agg_http, 1);
 	static char msg[AGG_BUF_LEN];
@@ -977,7 +985,7 @@
 	}
 }
 
-static void agg_export_buddies(struct gaim_connection *gc)
+static void export_buddies_server(struct gaim_connection *gc)
 {
 	struct agg_http *he = g_new0(struct agg_http, 1);
 	static char msg[AGG_BUF_LEN];
@@ -1023,6 +1031,27 @@
 	}
 }
 
+static void delete_buddies_server(struct gaim_connection *gc)
+{
+	struct agg_http *he = g_new0(struct agg_http, 1);
+	static char msg[AGG_BUF_LEN];
+
+	he->gc = gc;
+	he->type = AGG_HTTP_USERLIST_DELETE;
+	he->form = AGG_PUBDIR_USERLIST_EXPORT_FORM;
+	he->host = GG_PUBDIR_HOST;
+	he->request = g_strdup_printf("FmNum=%s&Pass=%s&Delete=1", gc->username, gc->password);
+
+	if (proxy_connect(GG_PUBDIR_HOST, GG_PUBDIR_PORT, http_req_callback, he) < 0) {
+		g_snprintf(msg, sizeof(msg), _("Deletion of Buddies List from Server failed (%s)"),
+			   GG_PUBDIR_HOST);
+		do_error_dialog(msg, _("Gadu-Gadu Error"));
+		g_free(he->request);
+		g_free(he);
+		return;
+	}
+}
+
 static void agg_dir_search(struct gaim_connection *gc, char *first, char *middle,
 			   char *last, char *maiden, char *city, char *state, char *country, char *email)
 {
@@ -1066,9 +1095,11 @@
 	if (!strcmp(action, _("Directory Search"))) {
 		show_find_info(gc);
 	} else if (!strcmp(action, _("Import Buddies List from Server"))) {
-		agg_import_buddies(gc);
+		import_buddies_server(gc);
 	} else if (!strcmp(action, _("Export Buddies List to Server"))) {
-		agg_export_buddies(gc);
+		export_buddies_server(gc);
+	} else if (!strcmp(action, _("Delete Buddies List from Server"))) {
+	        delete_buddies_server(gc);
 	}
 }
 
@@ -1079,6 +1110,7 @@
 	m = g_list_append(m, _("Directory Search"));
 	m = g_list_append(m, _("Import Buddies List from Server"));
 	m = g_list_append(m, _("Export Buddies List to Server"));
+	m = g_list_append(m, _("Delete Buddies List from Server"));
 
 	return m;
 }
--- a/src/protocols/gg/protocol.txt	Tue Nov 27 22:46:03 2001 +0000
+++ b/src/protocols/gg/protocol.txt	Tue Nov 27 22:54:32 2001 +0000
@@ -1,12 +1,20 @@
 ---------------------------------------------------------------------------
 
-                         protokół g*du-g*du 4.x
-        (c) copyright 2001 by wojtek kaniewski <wojtekka@irc.pl>
+                          Protokół G*du-G*du 4.x
+
+     (C) Copyright 2001 by Wojtek Kaniewski <wojtekka@irc.pl>,
+                           Robert J. Woźny <speedy@atman.pl>,
+                           Tomasz Jarzynka <tomee@cpi.pl>,
+                           Adam Ludwikowski <adam.ludwikowski@wp.pl>,
+                           Marek Kozina <klith@hybrid.art.pl>,
+			   Rafał Florek <raf@regionet.regionet.pl>,
+			   Igor Popik <igipop@wsfiz.edu.pl>
 
 --- 0) disclaimer ---------------------------------------------------------
 
-wszystkie informacje bazują na doświadczeniach przeprowadzonych na moim
-domowym komputerze. żaden klient g*du-g*du nie został skrzywdzony podczas
+opis protokołu bazują na doświadczeniach przeprowadzonych na moim
+domowym komputerze oraz informacjach przysłanych do mnie przez różnych
+ludzi. żaden klient g*du-g*du nie został skrzywdzony podczas
 przeprowadzania badań, blabla.
 
 --- 1) transmisja, format wszystkich pakietów -----------------------------
@@ -37,7 +45,19 @@
 	User-Agent: Mozilla/4.7 [en] (Win98; I)
 	Pragma: no-cache
 
-na co powinniśmy dostać odpowiedź w stylu:
+oryginalny klient może wysłać jeden z podanych identyfikatorów przeglądarki:
+
+	Mozilla/4.04 [en] (Win95; I ;Nav)
+	Mozilla/4.7 [en] (Win98; I)
+	Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)
+	Mozilla/4.0 (compatible; MSIE 5.0; Windows NT)
+	Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt)
+	Mozilla/4.0 (compatible; MSIE 5.0; Windows 98)
+
+nowsze wersje klienta do zapytania dodają również `version=...' opisujące,
+z jakim klientem serwer ma do czynienia. jednak ze względu na możliwe
+różnice w protokole, lepiej pomijać ten parametr i uwagać GG 4.0. w każdym
+razie na to zapytanie serwer powinien odpowiedzieć:
 
 	HTTP/1.0 200 OK
 	
@@ -47,10 +67,12 @@
 przemyślany i w przyszłości będzie można używać różnych serwerów do różnych
 rzeczy, typu szukanie, obsługa klientów itd. póki co, łączyć się trzeba na
 pierwszy adres (tak, ten z portem).
+Jeżeli połączenie z portem 8074 nie wyjdzie z jakiś specyficznych powodów -
+można się łączyć na port 443. 
 
 --- 3) logowanie się -------------------------------------------------------
 
-po połączeniu się portem 8074 serwera g*du-g*du, dostajemy pakiet typu 0x0001,
+po połączeniu się portem serwera g*du-g*du, dostajemy pakiet typu 0x0001,
 który na potrzeby tego dokumentu nazwiemy:
 
 	#define GG_WELCOME 0x0001
@@ -72,7 +94,7 @@
 		int uin;		/* twój numerek */
 		int hash;		/* hash hasła */
 		int status;		/* status na dzień dobry */
-		int dunno1;		/* == 0x0b */
+		int version;		/* wersja klienta */
 		int local_ip;		/* mój adres ip */
 		short local_port;	/* port, na którym słucham */
 	};
@@ -84,8 +106,19 @@
 	for (hash = 1; *passwd; passwd++)
 		hash *= (*passwd) + 1;
 
-zrozumiałe, racja? jeśli wszystko się powiedzie, dostaniemy w odpowiedzi
-pakiet typu
+zrozumiałe, racja? liczba oznaczająca wersję może być jedną z poniższych:
+
+	0x11 - 4.6.1
+	0x10 - 4.5.22, 4.5.21, 4.5.19, 4.5.17, 4.5.15
+	0x0f - 4.5.12
+	0x0b - 4.0.30, 4.0.29, 4.0.28, 4.0.25
+
+oczywiście nie są to wszystkie możliwe wersje klientów, lecz te, które
+udało się sprawdzić. najbezpieczniej będzie przedstawiać się jako ta
+wersja, której ficzerów używamy. wiadomo, że 4.0.x nie obsługiwały trybu
+ukrytego, ani tylko dla znajomych itd.
+
+jeśli wszystko się powiedzie, dostaniemy w odpowiedzi pakiet typu
 
 	#define GG_LOGIN_OK 0x0003
 
@@ -137,14 +170,16 @@
 		int status;		/* status danej osoby */
 		int remote_ip;		/* adres ip delikwenta */
 		short remote_port;	/* port, na którym słucha klient */
-		int dunno1;		/* == 0x0b */
-		short dunno2;		/* znowu port? */
+		int version;		/* wersja klienta */
+		short dunno1;		/* znowu port? */
 	};
 
 jeśli klient nie obsługuje połączeń między klientami (np. g*du-g*du 3.x)
-zamiast adresu ip jest 0, zamiast portu jest 2. nieważne ;) w każdym razie,
-jeśli ktoś się pojawi w trakcie pracy, również zostanie przysłany ten
-pakiet. proste? proste :)
+zamiast adresu ip jest 0, zamiast portu może być 0, 1, 2... nieważne ;)
+port może przyjmować wartość 1, jeśli klient znajduje się za jakimś
+firewallem lub innym urządzeniem robiącym NAT. w każdym razie, jeśli ktoś
+się pojawi w trakcie pracy, również zostanie przysłany ten pakiet.
+proste? proste :)
 
 żeby dodać kogoś do listy w trakcie pracy, trzeba wysłać niżej opisany
 pakiet. jego format jest identyczny jak przy GG_NOTIFY.
@@ -171,8 +206,10 @@
 
 	#define GG_SEND_MSG 0x000b
 
+	#define GG_CLASS_QUEUED 0x0001	/* tylko przy odbieraniu */
 	#define GG_CLASS_MSG 0x0004
 	#define GG_CLASS_CHAT 0x0008
+	#define GG_CLASS_UNKNOWN_1 0x0020
 
 	struct gg_send_msg {
 		int recipient;
@@ -186,8 +223,27 @@
 rozmowy za pomocą części bajtów, ale raczej nie ma znaczenia. klasa
 wiadomości pozwala odróżnić, czy wiadomość ma się pokazać w osobym
 okienku czy jako kolejna linijka w okienku rozmowy. wygląda na to,
-że to jakaś bitmapa, więc najlepiej olać inne bity niż 0x0f. (czasem
-klienty wysyłają 0x04, czasem 0x24)
+że to jakaś bitmapa, więc najlepiej olać inne bity niż 0x0e. (czasem
+klienty wysyłają 0x04, czasem 0x24 -- widocznie 0x20 to też jakaś
+flaga). jeśli odbiorca był niedostępny podczas wysyłania wiadomości,
+zostanie zaznaczony bit 0x01.
+
+oryginalny klient wysyłając wiadomość do kilku użytkowników, wysyła po
+prostu kilka takich samych pakietów z różnymi numerkami odbiorców. nie
+ma osobnego pakietu do tego. natomiast jeśli chodzi o ,,konferencyjnę''
+do pakietu doklejana jest za ,,char message[];'' następująca struktura:
+
+	struct gg_send_recipients {
+		char flag;		/* == 1 */
+		int count;		/* ilość odbiorców */
+		int recipients[];	/* tablica odbiorców */
+	};
+
+na przykład, by wysłać do trzech ludzi, należy wysłać pakiet:
+
+	- -- --- --+--+--+--+--+--+--+-----------+-----------+
+          treść    |\0|\1|    0x02   |    uin1   |   uin2    |
+	- -- -- ---+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
 serwer po otrzymaniu wiadomości odsyła informację o tym. przy okazji
 mówi, czy wiadomość dotarła do odbiorcy (status == GG_ACK_DELIVERED),
@@ -208,26 +264,29 @@
 
 --- 7) otrzymywanie wiadomości ---------------------------------------------
 
-zbyt wiele wyjaśnień chyba nie trzeba. wiadomo od kogo. nieznane pola to
-coś a'la numer sekwencyjny albo identyfikator okienka z rozmową albo nowe
-dane dla setiathome. klasa wiadomości taka sama jak przy wysyłaniu:
+zbyt wiele wyjaśnień chyba nie trzeba. wiadomo od kogo. drugie pole to
+najprawdopodobniej jakiś numerek sekwencyjny. trzecie oznacza czas nadania
+wiadomości. klasa wiadomości taka sama jak przy wysyłaniu:
 
 	#define GG_RECV_MSG 0x000a
 	
 	struct gg_recv_msg {
 		int sender;
-		int dunno1;
-		int dunno2;
+		int seq;
+		int time;
 		int class;
 		char message[];
 	};
 
---- 8) otrzymywanie wiadomości ---------------------------------------------
+w przypadku pakietów ,,konferencyjnych'' na koncu pakietu doklejona jest
+struktura identyczna ze struct gg_send_recipients zawierająca pozostałych
+rozmówców.
+
+--- 8) ping/pong -----------------------------------------------------------
 
 od czasu do czasu klient wysyła pakiet a'la ping do serwera i dostaje pustą
-odpowiedź. ciężko stwierdzić, czy serwer wywala, jeśli nie dostanie pinga
-przez jakiś czas, czy klient się rozłącza, jeśli serwer mu nie odpowie.
-jakoś nie chce mi się sprawdzać ;)
+odpowiedź. o ile dobrze pamiętam, serwer rozłącza się po upływie 5 minut od
+otrzymania ostatniej informacji.
 
 	#define GG_PING 0x0008
 	
@@ -239,10 +298,21 @@
 
 --- 9) podziękowania -------------------------------------------------------
 
-swój wkład w poznanie protokołu miał Robert Woźny, który opisał nowości
-w GG 4.6.
+swój wkład w poznanie protokołu mieli:
+ - Robert J. Woźny <speedy@atman.pl>:
+   opis nowości w protokole GG 4.6,
+ - Tomasz Jarzynka <tomee@cpi.pl>:
+   badanie timeoutów,
+ - Adam Ludwikowski <adam.ludwikowski@wp.pl>:
+   wiele różnych poprawek do tekstu, badanie wersji,
+ - Marek Kozina <klith@hybrid.art.pl>:
+   czas otrzymania wiadomości,
+ - Rafał Florek <raf@regionet.regionet.pl>:
+   konferencje,
+ - Igor Popik <igipop@wsfiz.edu.pl>:
+   klasy wiadomości przy odbieraniu zakolejkowanej.
 
 ----------------------------------------------------------------------------
 
-$Id: protocol.txt 2406 2001-09-29 23:06:30Z warmenhoven $
+$Id: protocol.txt 2819 2001-11-27 22:54:32Z warmenhoven $