# HG changeset patch # User Eric Warmenhoven # Date 1006901672 0 # Node ID 1ffac7cf4e94bc0887c81aae72c5a2ebe3ce3dad # Parent 9b3c7d2a6e9aa67d4c247d59007f4ca08afe661c [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 diff -r 9b3c7d2a6e9a -r 1ffac7cf4e94 src/protocols/gg/gg.c --- 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 * @@ -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; } diff -r 9b3c7d2a6e9a -r 1ffac7cf4e94 src/protocols/gg/protocol.txt --- 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 + Protokół G*du-G*du 4.x + + (C) Copyright 2001 by Wojtek Kaniewski , + Robert J. Woźny , + Tomasz Jarzynka , + Adam Ludwikowski , + Marek Kozina , + Rafał Florek , + Igor Popik --- 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 : + opis nowości w protokole GG 4.6, + - Tomasz Jarzynka : + badanie timeoutów, + - Adam Ludwikowski : + wiele różnych poprawek do tekstu, badanie wersji, + - Marek Kozina : + czas otrzymania wiadomości, + - Rafał Florek : + konferencje, + - Igor Popik : + 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 $