Re: [libgadu-devel] logowanie do GG nie działa po TLS
Widziałem, że Rafał w Kadu walczy z tym samym błędem: http://www.kadu.im/red mine/issues/3117 Wygląda na to, że jest częściowa poprawka w libgadu 1.12.2. Nie jestem pewien, jaki jest status tego wydania: tag w Gicie jest, ale nie widziałem żadnego ogłoszenia, a http://libgadu.net/ oraz htt ps://github.com/wojtekka/libgadu/releases/latest wciąż wskazują na 1.12.1. Tomek? --Bartek On Tue, Jan 31, 2017 at 3:23 PM, Dominik 'Rathann' Mierzejewski < domi...@greysector.net> wrote: > Witam i mam nadzieję, że ktoś tu jeszcze żyje. :) > > Otóż od jakiegoś czasu nie działa logowanie do GG po TLS. > System: Fedora 25 > pidgin-2.11.0 > libgadu-1.12.1 > > Oto log z pidgina (nr konta częściowo zaiksowany): > ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] Build libgadu dla win32
Po pobraniu dodatkowych siedmiu DLL-ek, od których ten build libgadu zależał (a właściwie libgnutls i sześciu jego zależności) i zmianie nazwy z libgadu-3.dll na gadu.dll działa z Kadu bez zarzutu. Pozdrawiam! ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] How to Report a Security Bug in libgadu
2013/6/15 Wojtek Kaniewski wojte...@toxygen.net: Dnia 2013-06-07, pią o godzinie 01:55 +0200, Bartosz Brachaczek pisze: So the functions of interest are: a) for OpenSSL: -- SSL_CTX_set_default_verify_paths() to use CA cert store configured during OpenSSL's build Does this function also verify the host name? It seems that it doesn't but I'd like to be sure before I start looking into it. Yeah, you're right. It doesn't. --Bartosz ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] How to Report a Security Bug in libgadu
2013/6/13 Wojtek Kaniewski wojte...@toxygen.net: I plan to copy and paste a part of GnuTLS' configure.ac. Take a look at https://gitorious.org/gnutls/gnutls/blobs/c59329a089a9ed108692066de95f533f482b5422/configure.ac line 377. And if we detect GnuTLS 3.x we'll use appropriate function. Are you okay with such solution? I'm fine with it. --Bartosz ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] How to Report a Security Bug in libgadu
2013/6/12 Wojtek Kaniewski wojte...@toxygen.net: As Bartosz wrote the code for GnuTLS will be more complicated, so it may take some time. Do you have any plan for it? I have performed some research and the options seem to be to: 1) Have a build-time option to explicitly specify a CA trust store file to use, and if not specified, default to the first existing of: /etc/ssl/certs/ca-certificates.crt (Debian, Gentoo, Arch), /etc/pki/tls/cert.pem (Fedora), /etc/ssl/ca-bundle.pem (OpenSUSE), /usr/local/share/certs/ca-root-nss.crt (FreeBSD), /etc/ssl/cert.pem (OpenBSD) If specified, we could use the configured file and ignore system default altogether for both OpenSSL and GnuTLS. But if it was guessed, probably we should rather use OpenSSL's and GnuTLS's (in case of GnuTLS 3.0 or newer) default. 2) Another option would be to simply hard-code all these paths for GnuTLS older than 3.0 and not provide any build-time option at all. And as I'm thinking about that, it actually seems to be the best option to me. 3) For the sake of completeness: We could also require GnuTLS v3, but it's really a no-go because we should fix this issue in the 1.11 line and raising library requirements to something that even Debian 7.0 doesn't have is a very bad idea. What do you think? --Bartosz ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] How to Report a Security Bug in libgadu
(Reposting my conversation with Wojtek to the mailing list. I have just noticed we switched away from it). 2013/6/7 Bartosz Brachaczek b.brachac...@gmail.com: 2013/6/6 Wojtek Kaniewski wojte...@toxygen.net: Dnia 2013-06-04, wto o godzinie 13:37 +0200, Bartosz Brachaczek pisze: But checking which certificates are accepted by the proprietary client should be straightforward, as the current version of it is written in XUL and uses xulrunner's/gecko's methods of verifying certificates. I can volunteer to check this. If it turns out that the proprietary client trusts a CA that is not universally trusted, we might want to trust the same one when connecting to the Gadu-Gadu network in libgadu. Right now they use RapidSSL certificate issued by Equifax Secure Certificate Authority. I can see their certificate in my Ubuntu, so I guess it would be a matter of setting some flag to verify against preinstalled certificates, adding them to a list of trusted CA's or something similar. That's right, I have incorrectly assumed OpenSSL is using system CA cert store by default, and it's not the case. So the functions of interest are: a) for OpenSSL: -- SSL_CTX_set_default_verify_paths() to use CA cert store configured during OpenSSL's build -- SSL_get_verify_result() to retrieve certificate verification result b) for GnuTLS: -- gnutls_certificate_set_x509_system_trust() to use default system CA cert store, requires GnuTLS = 3.0 so it can be problematic (alternatively gnutls_certificate_set_x509_trust_file() can be used to point to specific files; in OpenSSL that would of course be possible, too) -- gnutls_certificate_verify_peers2() and gnutls_x509_crt_check_hostname() to verify the certificate validity As for rejecting invalid certificates, what do you think about leaving behaviour for GG_SSL_ENABLED as is, but adding a obligatory check in case of GG_SSL_REQUIRED? This way users would be still able to use SSL (on their own risk) if the CA changed to something obscure. I think it makes sense. Regards, Wojtek ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] How to Report a Security Bug in libgadu
Hi, Simply using SSL_get_verify_result() is not a solution here, as it returns X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY when connecting to the proprietary servers on my system (I assume I am not being attacked, you might want to confirm it yourself). But checking which certificates are accepted by the proprietary client should be straightforward, as the current version of it is written in XUL and uses xulrunner's/gecko's methods of verifying certificates. I can volunteer to check this. If it turns out that the proprietary client trusts a CA that is not universally trusted, we might want to trust the same one when connecting to the Gadu-Gadu network in libgadu. Bartosz PS. I'm attaching a patch so you can easily check what does SSL_get_verify_result() return on your system. diff --git a/src/events.c b/src/events.c index 3f401e9..2cb104c 100644 --- a/src/events.c +++ b/src/events.c @@ -1145,6 +1145,10 @@ static gg_action_t gg_handle_tls_negotiation(struct gg_session *sess, struct gg_ X509_NAME_oneline(X509_get_issuer_name(peer), buf, sizeof(buf)); gg_debug_session(sess, GG_DEBUG_MISC, // cert issuer: %s\n, buf); + +long res = SSL_get_verify_result(GG_SESSION_OPENSSL(sess)); +if (res != X509_V_OK) +gg_debug_session(sess, GG_DEBUG_MISC, // WARNING! unable to verify peer certificate! res=%ld\n, res); } sess-state = next_state; 2013/6/4 Radhesh Krishnan K radheshkrishn...@gmail.com: Hi Wojtek, Sorry, I have a doubt. I would like to know how certificate validation is performed in the proprietary protocol and why something similar cannot be performed in this case? On Tue, Jun 4, 2013 at 4:41 AM, Wojtek Kaniewski wojte...@toxygen.net wrote: Dnia 2013-06-02, nie o godzinie 19:02 +0530, Radhesh Krishnan K pisze: I would like to report a security bug in libgadu. libgadu is using openSSL library for creating secure connections. (...) So the product using libgadu will be vulnerable to man-in-the-middle attack. It was rather a conscious decision. Since libgadu is a reverse-engineered implementation of a proprietary protocol, we have no control over the certificates used for SSL connections. We don't know which certificates will be accepted or rejected by the original client, so there is no reliable way to verify their validity in libgadu. But since you mentioned it, I guess we should at least add a note to the documentation. Regards, Wojtek -- Regards, Radhesh Krishnan K. ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] Implementacja protokołu GG11 w libgadu
W dniu 20 września 2012 22:01 użytkownik Jakub Zawadzki darkjames...@darkjames.pl napisał: Może da się to zaimplementować wykorzystując -timeout oraz -soft_timeout? (zgaduję, nie oglądałem kodu) Oczywiście, głupek ze mnie. Kombinowałem jak koń pod górkę, a zupełnie zapomniałem o soft_timeout. Duet timeout i soft_timeout idealnie się do tego nadaje. Dzięki ;). Tylko albo nie umiem szukać, albo z czwórki ekg, egk2, Kadu, libpurple tylko Kadu obsługuje soft_timeout[1]. Sprawdziłem z Kadu i działa to dokładnie tak, jak trzeba. Wystarczy w libgadu zrobić `sess-timeout = 1; sess-soft_timeout = 1;' w miejscu, z którego chcemy zlecić wysłanie potwierdzeń za sekundę i wysyłać je, tak jak wcześniej pisałem, z gg_send_queued_data() albo gdzieś indziej spod gg_watch_fd(). Trzeba też pamiętać o przywróceniu timeout i soft_timeout do normalnych wartości dla GG_STATE_CONNECTED (bo zakładam, że tylko w tym stanie używamy soft_timeout do zlecania zadań z opóźnieniem): diff --git a/src/events.c b/src/events.c index 3f401e9..b9e599a 100644 --- a/src/events.c +++ b/src/events.c @@ -1446,6 +1446,11 @@ struct gg_event *gg_watch_fd(struct gg_session *sess) return NULL; } + if (sess-state == GG_STATE_CONNECTED) { + sess-timeout = -1; + sess-soft_timeout = 0; + } + ge = malloc(sizeof(struct gg_event)); if (ge == NULL) { --- Bartosz [1] I to jeszcze kilka minut temu nie do końca poprawnie, bo przed poprawką, którą właśnie wrzuciłem, jawnie ignorowało wszelkie timeouty w stanie GG_STATE_CONNECTED. ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] Implementacja protokołu GG11 w libgadu
W dniu 20 września 2012 21:01 użytkownik Tomasz Wasilczyk tomkiewicz.gro...@gmail.com napisał: Natrafiłem jednak na pewien problem: nie można potwierdzać odebrania pakietów z obrazkami od razu po ich otrzymaniu. Zrobiłem więc bufor, w którym potwierdzam po trzy pakiety (udaję tak oryginalnego klienta). Wszystko fajnie działa, ale problem się pojawia, gdy nie znamy obrazka, który otrzymujemy (czasem się tak zdarza, że odbieramy niezamawiane obrazki, a właściwie tylko ich _fragmenty_). Podobnie jak przy znanych obrazkach, potwierdzam po trzy, ale jeżeli w buforze zostaną 1-2 pakiety, to nie mam jak ich potwierdzić (tzn. nie wiem, czy się da w libgadu wywołać jakiejś funkcji za jedną sekundę, żeby wyczyściła bufor). Zrobiłem to czyszczenie bufora w funkcji ping, ale klient może ją wywoływać nawet co 3.5 - 4 minuty (tak robi oryginalny klient), a my mamy na potwierdzenie 40 sekund. Z kolei jeżeli potwierdzimy za szybko (a jest taka możliwość, że ping wywoła się zaraz po odebraniu jakiegoś pakietu), to zostaniemy rozłączeni. Mam nadzieję, że opisałem to w miarę zrozumiale. Jakieś pomysły? Może dodatkowa funkcja podobna do ping, wywoływana przez klienta co 1s? Ale to chyba złamie API? Ja niestety (jak zwykle) nie rozumiem. 1. Rozumiem, że te niespodziewane pakiety są i tak do niczego nam niepotrzebne i potwierdzamy je tylko po to, żeby serwer nie zerwał połączenia? 2. W jaki sposób potwierdzasz jeden lub dwa ostatnie pakiety, których się spodziewałeś, jeśli liczba otrzymanych pakietów nie jest podzielna przez 3? 3. Z kodu wnioskuję, że co trzeci pakiet potwierdzasz jednak od razu. Więc widocznie potwierdzanie z opóźnieniem nie jest twardym wymogiem, a przynajmniej nie zawsze. Brałeś pod uwagę taką możliwość, że faktyczne znaczenie ma kolejność wysyłanych pakietów (w tym potwierdzeń), a nie odstępy czasowe między nimi? Bo przypuszczam, że skutkiem ubocznym takiego opóźniania jest zmiana kolejności ogólnie wysyłanych do serwera pakietów. Sprawdzałeś, jak zachowuje się oryginalny klient w przypadku takich niespodziewanych pakietów z obrazkami? -- chodzi mi konkretnie o analizę kolejności i odstępów czasowych wszelkich pakietów, jakie po czymś takim wysyła aż do momentu wysłania odpowiednich potwierdzeń. ### Druga sprawa: jeszcze trochę, a zaczął bym się gubić w tych wersjach łatek. Zrobiłem więc małego forka [1], do celów testowo-rozwojowych. Bibliotekę można testować z forkiem pidgina, korzystającym z jej nowych funkcji [2]. Myślę, że tak jest wygodniej zarówno dla Ciebie, jak i osób, które będą niedługo czytać i testować ten kod ;). Liczę na to, że ktoś w końcu zajrzy do tego kodu ;). Ja na pewno będę się z nim dokładnie zapoznawał, ale jeszcze nie wiem, kiedy. Plan jest taki, że w nadchodzących tygodniach mam więcej wolnego czasu, więc powinno się udać. I może pojawi się jakaś decyzja w sprawie tego modułu rozpakowującego pakiety - wciąż twierdzę, że moja wersja będzie bardziej czytelna i fajniejsza (kontrola typów, mniej kodu dla magic vars i nagłówków sekcji pakietu), ale to już Wasza decyzja. Moim zdaniem w takim razie możesz śmiało implementować Twoją wersję. Obie wersje są akceptowalne i mają swoje wady i zalety, ale to Ty jesteś teraz osobą piszczącą kod. Nie widzę powodu, żeby czekać, aż się Wojtek w tej sprawie wypowie, bo chyba na żadne inne głosy już tutaj nie liczyłeś. Zresztą w razie czego nie będzie problemu, żeby zmodyfikować lub całkowicie wymienić ten kod -- rozumiem, że to jest rzecz używana wyłącznie wewnątrz libgadu i nic innego nie będzie o niej wiedzieć. Bartosz ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] Implementacja protokołu GG11 w libgadu
W dniu 21 września 2012 00:38 użytkownik Tomasz Wasilczyk tomkiewicz.gro...@gmail.com napisał: 3. Z kodu wnioskuję, że co trzeci pakiet potwierdzasz jednak od razu. Więc widocznie potwierdzanie z opóźnieniem nie jest twardym wymogiem, a przynajmniej nie zawsze. Brałeś pod uwagę taką możliwość, że faktyczne znaczenie ma kolejność wysyłanych pakietów (w tym potwierdzeń), a nie odstępy czasowe między nimi? Bo przypuszczam, że skutkiem ubocznym takiego opóźniania jest zmiana kolejności ogólnie wysyłanych do serwera pakietów. Sprawdzałeś, jak zachowuje się oryginalny klient w przypadku takich niespodziewanych pakietów z obrazkami? -- chodzi mi konkretnie o analizę kolejności i odstępów czasowych wszelkich pakietów, jakie po czymś takim wysyła aż do momentu wysłania odpowiednich potwierdzeń. No tak, trzeci potwierdzam od razu. Właściwie, to jestem pewien tylko tego, że serwer nas rozłącza w przypadku natychmiastowej odpowiedzi na pierwszy pakiet. Ponadto też rozłączał po natychmiastowej odpowiedzi na jeden z pierwszych (pierwszy?) niespodziewanych pakietów (tego dokładnie nie sprawdzałem). Jeżeli chodzi o kolejność, to wygląda na to, że ta się nie zmienia w tym konkretnym przypadku testowym (odebranie obrazka) - oryginalny klient po prostu wysyła te potwierdzenia paczkami, ale nierównymi (po 3, 4, chyba czasem nawet jednym pakiecie). GG11 odpowiada na niespodziewane pakiety, tak jak na te spodziewane. Nie udało mi się jak na razie znaleźć jakiejś reguły. Jeszcze wspomnę o pochodzeniu tych niespodziewanych: jeżeli odbierzemy pół obrazka i zerwie się nam połączenie, drugie pół odbierze dowolna inna włączona później sesja. W rezultacie, jak odpowiadałem na te pakiety od razu, nie byłem w stanie włączyć Pidgina, zanim oryginalnym klientem nie wyczyściłem konta. Na pewno to będzie trzeba jeszcze pobadać, ale to nie jest łatwe zadanie, zważając na fakt, że oryginalny klient jeszcze gorzej sobie z tym radzi niż libgadu ;). Chyba zgłoszę to ich pomocy technicznej, może to naprawią. Faktycznie dobrze by było to zgłosić, żeby mieć na czym się wzorować, kiedy to już poprawią ;). Przy odrobinie szczęścia poprawią coś w oprogramowaniu serwerów na korzyść libgadu. Aczkolwiek jakoś w tym przypadku mam wrażenie, że to zrywanie połączenia przy natychmiastowej odpowiedzi to próba wyłapania zachowania, które świadczy o tym, że ktoś się nie łączy za pomocą oryginalnego klienta. Bo jakoś nie potrafię sobie wyobrazić technicznego powodu ku takiemu zachowaniu. Chyba, że to zwykły błąd, ale i tak nie mam pojęcia, jaki by to musiał być dziwny błąd, żeby tak się objawiać... A jeśli faktycznie będzie trzeba rozwiązać jakoś kwestię opóźnionego potwierdzania końcówek tych niezamawianych fragmentów obrazków, to ja niestety nie mam żadnego mądrego pomysłu. Jedyny sposób bez zmiany API, jaki wymyśliłem, to ustawianie w takim przypadku GG_CHECK_WRITE dopóki nie wyślemy tych potwierdzeń, co robilibyśmy tylko po upływie określonego czasu, mierzonego przez libgadu (mam nadzieję, że to nie musi być sekunda i na przykład 100 ms wystarczy). Wysyłanie, przynajmniej tych ostatnich, mogłoby być zrealizowane w gg_send_queued_data(). Skutek byłby taki, że aplikacja przez ten czas zjadałaby lwią część czasu jednego wątku procesora, bo każdy jej select() zwracałby od razu i aplikacja po nim wywoływałaby gg_watch_fd(). Brzmi tragicznie i wolałbym nie robić czegoś takiego, ale z drugiej strony jest to sytuacja naprawdę wyjątkowa i powinna się zdarzać bardzo, bardzo rzadko. Natomiast jeśli byśmy tutaj mieli troszkę zmieniać API, to zamiast kazać aplikacji wywoływać co sekundę jakąś nową funkcję, wolałbym dodać zdarzenie pt. wywołaj dodatkowe gg_watch_fd() za około sekundę albo coś podobnego. -- rozumiem, że to jest rzecz używana wyłącznie wewnątrz libgadu i nic innego nie będzie o niej wiedzieć. Dokładnie, tylko do wewnętrznego użytku. Boję się tylko sprawdzać, czy kolejność tych sekcji ma/nie ma znaczenia. Bo jeżeli nie ma, to chyba to skomplikuje kod. Ach, zapomniałem o tym. Niestety rzeczywiście należałoby to najpierw sprawdzić. ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] Implementacja protokołu GG11 w libgadu
W dniu 2 września 2012 16:28 użytkownik Tomasz Wasilczyk tomkiewicz.gro...@gmail.com napisał: Napisałem prototyp wspomnianego bufora [1], do odczytywania pakietów GG11 - nazwa robocza safe const buffer. Działa to w ten sposób, że sobie odczytujemy z takiego bufora po kolei co chcemy, a on sam pamięta w którym miejscu jest oraz czy nie wychodzimy poza bufor. Poprawność odczytu można sprawdzić jednorazowo, na samym końcu. W rezultacie, zamiast kodu [2], możemy uzyskać kod [3]. Co o tym myślicie? Mogę to spokojnie implementować i opierać obsługę gg11 o to narzędzie? To mi bardzo ułatwi pracę i poprawi jakość kodu. Poza tym, udało mi się przeanalizować część protokołu odpowiedzialną za konferencje i jestem w trakcie ich implementacji - jak skończę, to już chyba wszystkie pakiety gg11 będą obsługiwane. Poza tym cały czas poprawiam resztę protokołu - da się go już używać na co dzień, działa coraz stabilniej. Czekam na komentarze odnośnie bufora, Tomek [1] http://pastebin.com/DxW0rwpQ [2] http://pastebin.com/6UqCzxRz [3] http://pastebin.com/97cySfSg Sama idea mi się podoba. Chociaż nie nazywałbym tego buforem, bo wydaje mi się, że taka nazwa sugeruje, że ten obiekt jest właścicielem danych, które z niego czytamy. Wydaje mi się, że lepszą nazwą byłoby buffer reader (reader implikuje const) albo safe buffer reader, chociaż nie wiem, co ma oznaczać safe w tym przypadku. Ponadto zmieniłbym sygnaturę funkcji gg_scb_new() na void gg_scb_init(gg_scb *scb, const char *buffer, size_t length) -- taka wydaje mi się bardziej standardowa. Funkcje gg_scb_read_{uint{32,64},packed_uint}() zwracają inny typ, niż wskazuje ich nazwa (signed vs unsigned). Zmieniłbym również nazwy funkcji gg_scb_expected*() i gg_scb_required*() odpowiednio na gg_scb_expect*() i gg_scb_require*() -- skoro te funkcje mają obserwowalne efekty, ich nazwy powinny być imperatywami. Zastanawiam się też, czy jest potrzebne pole offset w strukturze gg_scb. Jak rozumiem, przesuwamy się w buforze wyłącznie do przodu, więc zamiast wskaźnika na początek i offsetu wystarczyłby tylko wskaźnik na aktualną pozycję. Wówczas zamiast pola length większy sens miałby wskaźnik na ostatni bajt buforu albo raczej jeden bajt za nim. Bartosz ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] Implementacja protokołu GG11 w libgadu
W dniu 2 września 2012 21:24 użytkownik Jakub Zawadzki darkjames...@darkjames.pl napisał: On Sun, Sep 02, 2012 at 04:28:04PM +0200, Tomasz Wasilczyk wrote: Napisałem prototyp wspomnianego bufora, do odczytywania pakietów GG11 - nazwa robocza safe const buffer. Działa to w ten sposób, że sobie odczytujemy z takiego bufora po kolei co chcemy, a on sam pamięta w którym miejscu jest oraz czy nie wychodzimy poza bufor. Poprawność odczytu można sprawdzić jednorazowo, na samym końcu. W rezultacie, zamiast kodu, możemy uzyskać kod. Co o tym myślicie? Mogę to spokojnie implementować i opierać obsługę gg11 o to narzędzie? To mi bardzo ułatwi pracę i poprawi jakość kodu. Ja raczej byłbym za stworzeniem funkcji podobnych do pack/unpack[1][2]. Rzeczywiście, taki interfejs wydaje się lepszym rozwiązaniem. Bartosz ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] Implementacja protokołu GG11 w libgadu
2012/8/30 Rafał Malinowski rafal.przemyslaw.malinow...@gmail.com: Hohohoh! Trzymamy kciuki w Kadu za to! Ja postaram się nie tylko trzymać kciuki, ale to jak znajdę znowu trochę czasu. ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] Cleanup of -Wall flags
2012/8/27 Daniel Macks dma...@netspace.org: Now that configure.ac puts -Wall in CFLAGS for the whole build process conditional on GCC, that same flag should not also be hardcoded in any specific makefiles. There are several instances of it in test/automatic/Makefile.am and test/manual/Makefile.am While working on that, I checked the automake documentation for CFLAGS, and I think test/automatic/Makefile.am has another problem as well. Defining that variable there overwrites CFLAGS that the user might set earlier (propagated from ./configure). AM_CFLAGS is the automake variable that the package-author controls instead: -CFLAGS = -Wall -ggdb -DGG_IGNORE_DEPRECATED +AM_CFLAGS = -ggdb -DGG_IGNORE_DEPRECATED message2 has its own _CFLAGS variable that overrides the more general AM_ one, so they need to be merged for that case: -message2_CFLAGS = @LIBXML2_CFLAGS@ +message2_CFLAGS = @LIBXML2_CFLAGS@ $(AM_CFLAGS) dan That particular issue with CFLAGS in test/automatic/Makefile.am is fixed in current svn trunk for some time already. The checkout url is http://toxygen.net/svn/libgadu/trunk if you want to have a look at this. I'm not saying the fixes are like super-correct or examples of good automake practices (they're not and I'll probably fix them sometime soon) but at least they work. Thanks, Bartosz ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] Kolejne zawodzące testy
W dniu 27 sierpnia 2012 09:17 użytkownik Marcin Owsiany mar...@owsiany.pl napisał: Jeśli wyślesz mi łatkę wcześniej, to mogę potestować. Racja. Łatka jest bardzo prosta. Załączyłem ją w pliku 0005-*.patch. Łatka 0006-*.patch może przy odrobinie szczęścia nieco rozjaśnić powód problemów na kFreeBSD. Bartosz 0005-Popraw-test-connect-pod-GNU-Hurd.patch Description: Binary data 0006-B-d-paranoiczny-je-li-chodzi-o-potencjalne-b-dy-w-te.patch Description: Binary data ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] Kolejne zawodzące testy
Dobra. Chyba poprawiłem też ten test na kFreeBSD. Załączam łatki. 0008-Zawsze-zeruj-struktur-sockaddr_in-valgrind-FreeBSD.patch Description: Binary data 0009-Popraw-implementacj-timeoutu-w-connect.patch Description: Binary data ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] Kolejne zawodzące testy
2012/8/18 Marcin Owsiany mar...@owsiany.pl: .. w r1314, na kfreebsd-i386 i hurd-i386, ale w różny sposób: https://buildd.debian.org/status/fetch.php?pkg=libgaduarch=kfreebsd-i386ver=1%3A1.12.0%7Epre%2Br1314-1stamp=1345247660 https://buildd.debian.org/status/fetch.php?pkg=libgaduarch=hurd-i386ver=1%3A1.12.0%7Epre%2Br1314-1stamp=1345256162 Mam poprawkę na problem z Test error (ten z Hurda). Brakowało continue po złapaniu EINTR w select(). Natomiast nie wiem jeszcze, co powoduje problem na kFreeBSD. Być może też gdzieś jest EINTR, a my tego nie obsługujemy. Wygląda na to, że na Linuksie nigdy nie dostajemy EINTR, jeśli nie mamy własnej obsługi sygnałów, ale gdzie indziej może się to zdarzyć (dziwne...). Wrzucę poprawki do repozytorium, jak tylko będzie to możliwe. Bo chwilowo serwer ma problemy, już napisałem Wojtkowi. Pozdrawiam, Bartosz ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] [libgadu-commit] r1307 - in trunk: . src test/automatic
W dniu 15 sierpnia 2012 16:05 użytkownik Wojtek Kaniewski wojte...@toxygen.net napisał: Dnia 2012-08-11, sob o godzinie 21:52 +0200, Libgadu commit list pisze: Author: beevvy Date: 2012-08-11 21:52:57 +0200 (Sat, 11 Aug 2012) New Revision: 1307 Modified: trunk/configure.ac trunk/src/sha1.c trunk/test/automatic/Makefile.am trunk/test/automatic/connect.c Log: Pozbądź się zależności od libgcrypt Świetnie! Mam jedynie zastrzeżenie do sprawdzania wyniku funkcji SHA1*. One zwracają coś od OpenSSL 0.9.7, więc jeśli ktoś spróbuje kompilować ze starszą wersją, będzie miał problemy. Grzebanie w openssl.m4 to dość karkołomne zadanie, więc może chociaż wspomnieć o tym w README? Rzeczywiście, zupełnie zapomniałem, że wypada informować o wymaganych wersjach zależnych bibliotek. Poprawiłem to w r1313. Dzięki za zwrócenie uwagi. Poza tym, GnuTLS umie liczyć hashe od zawsze czy też od którejś wersji, którą powinniśmy sprawdzać za pomocą pkg-config? Od wersji 2.10.0 wydanej w czerwcu 2010. Również to doprecyzowałem. Mam nadzieję, że to nie za duże wymaganie. ;) Pozdrawiam ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] Testy zawodzą na GNU/kFreeBSD
W dniu 16 czerwca 2012 22:47 użytkownik Wojtek Kaniewski wojte...@toxygen.net napisał: Dnia 2012-06-16, sob o godzinie 19:22 +0100, Marcin Owsiany pisze: Witam, log z autobuildera: https://buildd.debian.org/status/fetch.php?pkg=libgaduarch=kfreebsd-amd64ver=1%3A1.12.0~pre%2Br1278-1stamp=1339864900file=log Jakieś pomysły? Jesteś w stanie zgarnąć plik tests/automatic/report.html z maszyny budującej? report.html? Z tego, co widzę, to nie powiódł się test protocol, a nie connect, który generuje report.html. I akurat tak się składa, że wczoraj napisałem poprawkę na test protocol, która powinna tutaj pomóc -- postaram się ją jeszcze dzisiaj wrzucić. Pozdrawiam, Bartosz ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] Testy zawodzą na GNU/kFreeBSD
W dniu 16 czerwca 2012 23:03 użytkownik Bartosz Brachaczek b.brachac...@gmail.com napisał: I akurat tak się składa, że wczoraj napisałem poprawkę na test protocol, która powinna tutaj pomóc -- postaram się ją jeszcze dzisiaj wrzucić. Poprawka polegała na tym, że używane były sockety AF_UNIX zamiast AF_INET, ale to wiązało się z koniecznością dodania własnej wersji gg_connect() do testu. Więc to, co zrobił Wojtek, jest raczej lepsze. :) ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] [libgadu-commit] r1269 - trunk/src
W dniu 13 czerwca 2012 23:20 użytkownik Wojtek Kaniewski wojte...@toxygen.net napisał: Tak się zastanawiam... Jest jakiś konkretny powód, dla którego mielibyśmy obsługiwać EAGAIN? Kręcenie się w kółko zżerając 100% procesora, gdy aplikacja zrobi coś głupiego, to na pewno najlepsze wyjście? :) To bardzo kiepskie wyjście. ;) Zdążyłem już dojść do tego samego wniosku, patrz r1276. Pozdrawiam, Bartosz ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] [libgadu-commit] r1262 - in trunk: . pkgconfig
W dniu 13 czerwca 2012 19:55 użytkownik Wojtek Kaniewski wojte...@toxygen.net napisał: libgadu.h zawiera #include openssl/ssl.h. Jesteś pewny, że powinno iść do .private? Tak, pkgconfig doda ścieżki do inkludów tak czy inaczej. Polecam przeczytać Guide to pkg-config[1], w szczególności dwa ostatnie punkty FAQ. Kilka minut czytania i wie się więcej o pkgconfig, niż zdecydowana większość programistów. :) Pozdrawiam [1] http://people.freedesktop.org/~dbn/pkg-config-guide.html ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] Wątpliwości co do ustawiania soft_timeout w events.c
W dniu 5 marca 2012 00:02 użytkownik Wojtek Kaniewski wojte...@toxygen.net napisał: Dnia 2012-03-03, sob o godzinie 18:46 +0100, Bartosz Brachaczek pisze: Wiem, że powyższa sytuacja to głównie wina błędu w Kadu, ale _wydaje mi się_, że w gg_handle_connecting() w libgadu powinno nastąpić ustawienie soft_timeout na 0. Czy może czegoś tutaj nie rozumiem? Dobrze Ci się wydaje. Flaga soft_timeout ma być używana przy próbach połączenia, żeby móc próbować łączyć się z kolejnymi adresami IP. Inaczej mogą dziać się dziiiwne rzeczy. Poprawisz czy ja mam to zrobić? Dzięki. :) Poprawiłem. Pozdrawiam ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] gg_send_packet() a EAGAIN
2011/12/28 Jakub Zawadzki darkjames...@darkjames.pl: On Wed, Dec 28, 2011 at 01:28:12PM +0100, Jakub Zawadzki wrote: Spróbuj z r1240 (...) Oczywiście chodziło mi o r1242, zły dzień ;| Dzięki, pomogło. A wiadomość z Spróbuj z r1240 w ogóle do mnie nie doszła. Przeglądając archiwum listy przez www, również nie widzę żadnych wiadomości nowszych niż z 16 grudnia. Czy z tą listą nie jest coś nie tak? Pozdrawiam ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
[libgadu-devel] Niedziałająca obsługa OpenSSL
Cześć, W obecnym trunku obsługa OpenSSL jest zepsuta. Mianowicie w gg_session_init_ssl() wywoływane jest SSL_CTX_new() pod warunkiem, że gs-ssl_ctx != NULL, podczas gdy powinno być wywoływane pod przeciwnym warunkiem. Sam nie wrzucam poprawki, bo nie wiem, czy dla przypadku gs-ssl_ctx != NULL ma być SSL_CTX_free() i stworzenie nowego obiektu, tak jak jest z gs-ssl, czy też nie mamy wtedy nic z tym robić. Pozdrawiam, Bartosz ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
[libgadu-devel] libgadu 1.11.1?
Hej, Czy byłoby możliwe wydanie libgadu 1.11.1? Powód mojego pytania jest taki, że w libgadu 1.11.0 nie działają połączenia szyfrowane z użyciem GnuTLS, a w obecnej gałęzi 1.11 jak najbardziej działają (działają również połączenia z użyciem OpenSSL, tak samo jak w 1.11.0). Zbliża się nowe wydanie Kadu i najchętniej byśmy włączyli w nim domyślnie połączenia szyfrowane i wymagali przynajmniej libgadu 1.11.1. Z tego, co patrzałem, to od ostatniego merge'a Wojtka nie znalazły się w trunku żadne poprawki godne gałęzi 1.11, chyba że moje dwa ostatnie commity poprawiające drobnostki (r1240 i r1241) oraz oczywiście ewentualna poprawka na problem z EAGAIN, który opisałem tu godzinę temu. Pozdrawiam, Bartosz ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
[libgadu-devel] HAVE_STRTOULL i HAVE_UINT64_T a dcc7
Cześć, Kawałek kodu w src/dcc7.c (a także kod na usługach dcc7 w include/internal.h i src/endian.c) zależy od zdefiniowanych makr HAVE_STRTOULL i HAVE_UINT64_T.. Tak się jednak składa, że te makra są jedynie definiowane w config.h (include/libgadu.h.in nic o nich nie wie), a żaden ze wspomnianych plików config.h nie includuje, więc i kod zależny od istnienia tych makr nigdy nie jest kompilowany. Co do HAVE_STRTOULL, wydaje mi się, że można je zastąpić GG_CONFIG_HAVE_STRTOULL (a także GG_CONFIG_HAVE__STRTOUI64 na potrzeby MSVC). Natomiast istnienie HAVE_UINT64_T jest dla mnie trochę dziwne, bo przecież jest już GG_CONFIG_HAVE_LONG_LONG. Co z tym zrobić? Pozdrawiam, Bartosz ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] Nieprawidłowe działanie gg_vsaprintf w niektórych konfiguracjach
W dniu 29 października 2011 18:53 użytkownik Wojtek Kaniewski wojte...@toxygen.net napisał: Dnia 2011-10-29, sob o godzinie 02:35 +0200, Bartosz Brachaczek pisze: W załączonych łatkach moim zdaniem są błędy off-by-one, podobnie zresztą jak jest w aktualnym kodzie libgadu. Przypadek res == size oznacza, że wszystkie znaki poza nullem zostały zapisane i implementacje niezgodne z C99, w szczególności MSVC, mogą takie coś zwrócić. Natomiast przypadek res == size - 1 oznacza, że wszystko idealnie się zmieściło. Nie mogę znaleźć res == size w aktualnym kodzie. Faktycznie, jest błąd polegający na tym, że jeśli mamy idealnie dopasowany bufor, to go powiększy jeszcze raz, ale to chyba nie jest krytyczny błąd? A mi się zdaje, że w aktualnym kodzie dla nie-C99 jeśli res == size, to żaden warunek z do... while nie będzie spełniony, czyli pętla się przerwie i zostawi bufor o 1 bajt za mały. A później, ze względu na zauważoną przez Tomka niespójność w użyciu size, vsnprintf zostanie wywołane z drugim argumentem o 1 większym niż faktyczny rozmiar bufora, czyli końcowy null zostanie zapisany do nie naszego obszaru w pamięci. Poza tym, nie wiem czy można sobie spokojnie kopiować va_list jeśli nie ma va_copy(). Sam to wymyśliłeś, czy wzorowałeś się na czymś? Wzorowałem się na opisie va_copy() z man stdarg(3)[1], a także na kilku linkach znalezionych w sieci[2][3][4][5]. Teraz trochę dokładniej przeczytałem [2] i wygląda na to, że akurat w przypadku MSVC va_copy() ani odpowiednik w ogóle nie jest potrzebny. Ale lepiej to sprawdzę. W [4] pojawia się również wzmianka o _vscprintf() i myślę, że warto by z tej funkcji skorzystać. Załączam niekompletną łatkę (zamiast prawidłowego wykrywania w configure.ac jest warunkowy #define dla MSVC w libgadu.h). Ponadto w pętli dla nie-C99 brakowało dodatkowych va_copy(). Kolejny problem to brak implementacji va_copy() dla MSVC. Tyle że va_copy() pojawiło się oficjalnie w C99. Wydaje mi się, że jeśli na danej platformie jest vsnprintf() zgodne z C99, ale stdarg.h już nie, to ma dużo większe problemy niż libgadu ;) Jasne, ale my va_copy() potrzebujemy wszędzie, chyba że akurat na danej platformie z przyczyn wynikających ze szczegółów implementacyjnych nie jest to konieczne. Nic nie stoi na przeszkodzie, aby jakaś platforma nie w ogóle wspierała C99, ale by użycie odpowiednika va_copy() było na niej konieczne. Jeśli MSVC faktycznie nie potrzebuje va_copy(), to nie jestem w stanie takiej wymienić, ale kto wie ;). Pozdrawiam, Bartosz [1] http://linux.die.net/man/3/stdarg [2] http://stackoverflow.com/questions/558223/va-copy-porting-to-visual-c [3] http://stackoverflow.com/questions/2288680/reuse-of-va-list [4] http://kerneltrap.org/mailarchive/git/2009/8/17/9549/thread [5] http://lists.freedesktop.org/archives/mesa-commit/2011-January/028533.html From c97d622f96ebad16f0558c3da82075634cbeb867 Mon Sep 17 00:00:00 2001 From: Bartosz Brachaczek b.brachac...@gmail.com Date: Fri, 28 Oct 2011 23:41:01 +0200 Subject: [PATCH] =?UTF-8?q?Dodaj=20obs=C5=82ug=C4=99=20=5Fvscprintf()=20dost?= =?UTF-8?q?=C4=99pnego=20w=20MSVC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/libgadu.h.in |4 src/common.c | 19 --- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/include/libgadu.h.in b/include/libgadu.h.in index d0b63b2..c8feafb 100644 --- a/include/libgadu.h.in +++ b/include/libgadu.h.in @@ -88,6 +88,10 @@ extern C { #define GG_CONFIG_HAVE_C99_VSNPRINTF #endif +#ifdef _MSC_VER +#define GG_CONFIG_HAVE__VSCPRINTF +#endif + /* Defined if this machine has va_copy(). */ #undef GG_CONFIG_HAVE_VA_COPY diff --git a/src/common.c b/src/common.c index afd9c7a..870c37b 100644 --- a/src/common.c +++ b/src/common.c @@ -70,7 +70,7 @@ char *gg_vsaprintf(const char *format, va_list ap) char *buf = NULL; va_list aq; -#ifndef GG_CONFIG_HAVE_C99_VSNPRINTF +#if !defined(GG_CONFIG_HAVE_C99_VSNPRINTF) !defined(GG_CONFIG_HAVE__VSCPRINTF) { int res = 0; char *tmp; @@ -96,19 +96,24 @@ char *gg_vsaprintf(const char *format, va_list ap) } while (res = size || res 0); } #else + va_copy(aq, ap); + +# if defined(GG_CONFIG_HAVE__VSCPRINTF) + size = _vscprintf(format, aq) + 1; +# else { char tmp[2]; - va_copy(aq, ap); /* libce Solarisa przy buforze NULL zawsze zwracają -1, więc * musimy podać coś istniejącego jako cel printf()owania. */ size = vsnprintf(tmp, sizeof(tmp), format, aq) + 1; - va_end(aq); - if (!(buf = malloc(size))) - return NULL; - - vsnprintf(buf, size, format, ap); } +# endif + va_end(aq); + if (!(buf = malloc(size))) + return NULL; + + vsnprintf(buf, size, format, ap); #endif return buf; -- 1.7.7.1 ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] Wyciek pliku w dcc (dcc6)
W dniu 28 października 2011 06:59 użytkownik Wojtek Kaniewski wojte...@toxygen.net napisał: Dnia 2011-10-28, pią o godzinie 00:59 +0200, Bartosz Brachaczek pisze: W ramach prac nad portem Win32 przeglądałem użycia funkcji close() w libgadu i stwierdziłem, że wszystkie jej wywołania w pliku dcc.c dotyczą gniazd. W związku z czym wydaje mi się, że brakuje close(d-file_fd) w gg_dcc_free(). Też to zauważyłem wczoraj. Nawet przejrzałem wzorcową implementację pt. ekg i nie ma tam zamykania tego deskryptora, więc jak najbardziej. Dodasz przy okazji zmian dla Win32 czy mam od razu to poprawić? Pozwoliłem sobie to teraz osobno poprawić, chyba się nie pomyliłem ;). Pozdrawiam, Bartosz ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] libpurple'owy fork - synchronizacja z upstream
To ja może podsumuję tutaj znane mi problemy pod MSVC i Win32 ogólnie: - Na Win32 obecnie nie można polegać na errno, bo funkcje Windows Sockets go nie ustawiają. Mam na to prawie gotową łatę w duchu sugestii Wojtka z tego wątku. - Na Win32 gniazda trzeba zamykać za pomocą closesocket(), ale pliki nadal za pomocą close() (właściwie _close(), ale close() też działa). Ja mam na to łatę w postaci funkcji gg_closesocket() opakowującej odpowiednią funkcję systemową. Jedyne, co mi tu się troszkę nie podoba, to ta nazwa wskazująca na gniazdo, a muszę jej używać również w przypadku deskryptorów resolvera. Technicznie oczywiście nie ma tu problemu, bo na Win32 one muszą być gniazdami, a gdzie indziej i tak to się sprowadza do zwykłego close(). - Na Win32 deskryptory gniazd to liczby bez znaku (w 32-bitowej bibliotece rozmiaru inta, w 64-bitowej niestety większe, czym zacznę się martwić po rozwiązaniu tutaj opisanych problemów) i zgodnie z MSDN nic nie stoi na przeszkodzie, aby wartością tej liczby było np. UINT_MAX-1 (UINT_MAX to INVALID_SOCKET, co na szczęście odpowiada -1). A widziałem w jednym miejscu kod typu if ((fd = sockfunc(...)) 1), który na taką wartość nie jest odporny. Myślę, że trzeba by zlokalizować takie miejsca i warunek zamienić na przykład na (fd == 0 || fd == -1). - MSVC odmawia kompilacji pustej struktury gg_dcc7_dunno1. Jak dla mnie można by ją spokojnie usunąć lub zakomentować. - MSVC nie posiada nagłówków unistd.h i inttypes.h. Ten drugi jest używany w message.h nie patrząc się na config.h, co chyba można by jakoś zmienić. - Pliki dcc.c, dcc7.c i sha1.c w katalogu src pod MSVC potrzebują nagłówka io.h, który definiuje część rzeczy znanych z unistd.h w GCC. - MSVC nie definiuje S_IWUSR, natomiast definiuje jego przedposixowy synonim S_IWRITE. - MSVC nie posiada funkcji snprintf, posiada natomiast _snprintf, która jest co prawda niezgodna z C99, ale na potrzebny libgadu powinna wystarczyć. - MSVC nie posiada funkcji strcasecmp ani strncasecmp, ale posiada ich dokładne odpowiedniki stricmp i strnicmp. - MSVC nie akceptuje arg... jako argument makra. Wydaje mi się, że mam na to proste rozwiązanie, ale muszę je przetestować. Powrzucałbym skończone łatki, jakie mam, do repozytorium libgadu, ale nie mam do końca wyczucia, które z kilku możliwych rozwiązań każdego problemu jest najbardziej pożądane. Chyba wrzucę to wszystko do jakiegoś zewnętrznego repozytorium, tak jak zresztą już wcześniej planowałem. Pozdrawiam, Bartosz ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] Nieprawidłowe działanie gg_vsaprintf w niektórych konfiguracjach
W załączonych łatkach moim zdaniem są błędy off-by-one, podobnie zresztą jak jest w aktualnym kodzie libgadu. Przypadek res == size oznacza, że wszystkie znaki poza nullem zostały zapisane i implementacje niezgodne z C99, w szczególności MSVC, mogą takie coś zwrócić. Natomiast przypadek res == size - 1 oznacza, że wszystko idealnie się zmieściło. Ponadto w pętli dla nie-C99 brakowało dodatkowych va_copy(). Kolejny problem to brak implementacji va_copy() dla MSVC. Załączam moją wersję łatki. Pozdrawiam, Bartosz From ea2965b436c8f491587b8915d3b9da469ed90c26 Mon Sep 17 00:00:00 2001 From: Bartosz Brachaczek b.brachac...@gmail.com Date: Sat, 29 Oct 2011 01:40:33 +0200 Subject: [PATCH] Popraw gg_vsaprintf() dla nie-C99 --- src/common.c | 58 -- 1 files changed, 28 insertions(+), 30 deletions(-) diff --git a/src/common.c b/src/common.c index 14eb5f3..afd9c7a 100644 --- a/src/common.c +++ b/src/common.c @@ -43,6 +43,14 @@ #include libgadu.h +#ifndef GG_CONFIG_HAVE_VA_COPY +# ifdef GG_CONFIG_HAVE___VA_COPY +#define va_copy(dest, src) __va_copy((dest), (src)) +# else +#define va_copy(dest, src) (dest) = (src) +# endif +#endif + /** * \internal Odpowiednik funkcji \c vsprintf alokujący miejsce na wynik. * @@ -58,59 +66,49 @@ */ char *gg_vsaprintf(const char *format, va_list ap) { - int size = 0; + int size; char *buf = NULL; - -#ifdef GG_CONFIG_HAVE_VA_COPY va_list aq; - va_copy(aq, ap); -#else -# ifdef GG_CONFIG_HAVE___VA_COPY - va_list aq; - - __va_copy(aq, ap); -# endif -#endif - #ifndef GG_CONFIG_HAVE_C99_VSNPRINTF { - int res; + int res = 0; char *tmp; size = 128; do { - size *= 2; + if (res size) { +/* Jednak zachowanie zgodne z C99. */ +size = res + 1; + } else { +size *= 2; + } + if (!(tmp = realloc(buf, size))) { free(buf); return NULL; } + buf = tmp; - res = vsnprintf(buf, size, format, ap); - } while (res == size - 1 || res == -1); + va_copy(aq, ap); + res = vsnprintf(buf, size, format, aq); + va_end(aq); + } while (res = size || res 0); } #else { char tmp[2]; + va_copy(aq, ap); /* libce Solarisa przy buforze NULL zawsze zwracają -1, więc * musimy podać coś istniejącego jako cel printf()owania. */ - size = vsnprintf(tmp, sizeof(tmp), format, ap); - if (!(buf = malloc(size + 1))) + size = vsnprintf(tmp, sizeof(tmp), format, aq) + 1; + va_end(aq); + if (!(buf = malloc(size))) return NULL; - } -#endif -#ifdef GG_CONFIG_HAVE_VA_COPY - vsnprintf(buf, size + 1, format, aq); - va_end(aq); -#else -# ifdef GG_CONFIG_HAVE___VA_COPY - vsnprintf(buf, size + 1, format, aq); - va_end(aq); -# else - vsnprintf(buf, size + 1, format, ap); -# endif + vsnprintf(buf, size, format, ap); + } #endif return buf; -- 1.7.7 ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] libpurple'owy fork - synchronizacja z upstream
W dniu 24 października 2011 07:28 użytkownik Wojtek Kaniewski wojte...@toxygen.net napisał: No tak, API. To trzeba będzie zrobić warunek, że ustawienie GG_RESOLVER_CUSTOM powoduje użycie read(), a wbudowane recv(), mimo że w praktyce pewnie nikt nigdy nie korzystał z oryginalnego libgadu na Win32. Wówczas GG_RESOLVER_CUSTOM i tak nie będzie działać na Win32. Zdaje mi się, że jedyny sposób na zachowanie kompatybilności pod Unix-like to jednak ifdefy dla Win32 w tych dwóch, trzech miejscach w obsłudze resolvera w libgadu. Pozdrawiam, Bartosz ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] libpurple'owy fork - synchronizacja z upstream
W dniu 23 października 2011 23:25 użytkownik Wojtek Kaniewski wojte...@toxygen.net napisał: Dnia 2011-10-23, nie o godzinie 03:11 +0200, Bartosz Brachaczek pisze: Właściwie żeby móc polegać na errno, to trzeba by coś takiego zrobić dla wszystkich funkcji socketowych, tj. także socket(), bind(), accept() itd. Tak czy inaczej jest to mniej inwazyjna metoda niż gg_socket_errno() + gg_socket_strerror(). Jeśli nie masz czasu/ochoty, mogę się zmusić do zainstalowania cygwina i/lub Visual Studio Express. Nie ma takiej potrzeby, i tak zamierzam to sam zrobić :). Ponadto z read()/write() vs recv()/send() jest jeszcze jeden problem. Mianowicie pipe'y w resolverze w forkach libpurple oraz Kadu są zrealizowane za pomocą socketów, a nie windowsowych pipe'ów. Nie sprawdzałem, czy to faktycznie konieczne, ale zgodnie z komentarzem do funkcji socket_pipe(), powodem jest niemożliwość wywołania select() na windowsowych pipe'ach. Jeśli tak ma zostać, to konieczna byłaby załączona łatka. Wolę dodać implementację socketpair() dla Win32 i mieć mniej #ifdefów, patrz r1192. W r1192 chyba zapomniałeś wkomitować network.c ;). Poza tym w tych miejscach z read()/write(), które dotykała łatka z mojej poprzedniej wiadomości, nadal jest potrzebne recv()/send(), aby to działało na Win32 (ostateczne to write() można by pominąć, bo dotyczy tylko pthread, ale nie zaszkodzi). Z drugiej strony w dokumentacji gg_session_set_custom_resolver() zostawiłeś możliwość stworzenia potoku lub innego deskryptora przez resolver ustawiany przez aplikację, a o ile mi wiadomo, recv() zadziała tylko dla gniazda. Pozdrawiam, Bartosz ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] Kodowanie zaszyfrowanych wiadomosci
W dniu 15 września 2011 01:18 użytkownik Bartosz Brachaczek b.brachac...@gmail.com napisał: W dniu 3 września 2010 22:54 użytkownik Jakub Zawadzki darkja...@darkjames.ath.cx napisał: Witam, Nieoficjalnym standardem[1] szyfrowania wiadomości w gg jest wykorzystanie kluczy RSA w kodowaniu WINDOWS-1250. W ekg2 jak implementowaliśmy obsługę UTF-8 w gg, niechcący zmieniliśmy również kodowanie szyfrowanej wiadomości ;) Zastanawiam się czy w pozostałych projektach nastąpiła podobna zmiana a jeśli nie to na ile chętni bylibyście ją przeprowadzić? Jeśli chcemy (a miłoby było) zachować kompatylibność ze starymi klientami. To w nagłówku sim_message_header jest pole 'flags' w których można by zachować informacje o kodowaniu. Ktoś może wie które bity z niego są używane? #v+ typedef struct { unsigned char init[8]; uint16_t magic; /* SIM_MAGIC_V1 0x2391 */ uint8_t flags; } sim_message_header; #v- [1] http://ekg.chmurka.net/docs/sim.txt ekg,ekg2,Kadu,PowerGG ktoś jeszcze? Cześć, Odnalazłem tę trochę starą wiadomość i stwierdzam, że Kadu jest bardzo zainteresowane obsługą UTF-8 w szyfrowaniu sim. Pole 'flags' jest przez ekg, ekg2 i Kadu (tyle sprawdziłem) w ogóle nieużywane, ale memset zapewnia jego wartość równą 0. Korzystając z wolnego czasu zrobiłem wstępną implementację w Kadu[1] i z moich testów wynika, że działa to całkiem sprawnie i zachowuje kompatybilność ze starymi wersjami. Moja propozycja flag jest taka: /* Flaga oznaczająca, że potrafimy przyjąć wiadomość UTF-8. Ustawiamy zawsze. */ #define SIM_FLAG_SUPPORT_UTF8 0x01 /* Flaga oznaczająca, że wiadomość, którą właśnie wysyłamy, jest zakodowana w UTF-8. Powinniśmy jej używać po otrzymaniu od rozmówcy wiadomości z flagą SIM_FLAG_SUPPORT_UTF8. */ #define SIM_FLAG_UTF8_MESSAGE 0x02 Kadu zapamiętuje, czy dany rozmówca wspiera UTF-8 również pomiędzy uruchomieniami programu, ale nie jest to funkcja konieczna ani nawet szczególnie istotna. Pozdrawiam, Bartosz [1] branch simlite-utf8, istotne commity: http://gitorious.org/kadu/kadu/commit/18a1f5c http://gitorious.org/kadu/kadu/commit/8c33c9a Odzewu się niestety nie doczekałem, ale i tak postanowiłem zmerdżować tego brancha do głównej gałęzi, więc ta funkcja znajdzie się w Kadu 0.11.0. Do czasu wydania rzecz podlega jeszcze ewentualnym modyfikacjom, ale później oczywiście wolałbym, żeby zostało, jak jest. Pozdrawiam, Bartosz ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] libpurple'owy fork - synchronizacja z upstream
W dniu 21 października 2011 01:31 użytkownik Tomasz Wasilczyk tomkiewicz.gro...@gmail.com napisał: Prawdopodobnie w libgadu mógł by się przydać resolver dla win32, który udało mi się wyciągnąć poza źródła libgadu dzięki dodaniu gg_global_set_custom_resolver. Bo w tej chwili windowsowe buildy będą bez żadnego. Ale to już nie jest istotne z punktu widzenia libpurple. Za to by się pewnie mogło przydać w Kadu. Kadu obecnie również ustawia własny resolver oparty o Qt, i to na wszystkich platformach. Co ciekawe właściwie jedyny powód jest taki, że pod Mac OS X w czasie migracji na libgadu 1.9.0 nie działał resolver z libgadu. Przypuszczam, że mogło to zostać poprawione od tego czasu w libgadu w r1051 i r1119, więc tego resolvera moglibyśmy się pozbyć. A wtedy faktycznie przydałby się działający resolver Win32 w libgadu (niestety nie wiem, na ile działa lub nie działa ten, który znajduje się w naszym forku, ani nawet skąd on tam się wziął). Pozdrawiam, Bartosz ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] libpurple'owy fork - synchronizacja z upstream
W dniu 18 października 2011 16:41 użytkownik Tomasz Wasilczyk tomkiewicz.gro...@gmail.com napisał: Nie rozumiem tylko, w jaki sposób bez niektórych z tych zmian wychodzą np. nowe wersje Kadu pod Windows. Kadu pod Windows ma własnego forka libgadu[1]. Z tego co wiem, część kodu dla Windows została napisana parę lat temu przez Michała Podsiadlika, a mniej więcej rok temu kod ten przeportował Tomasz Rostański do nowszej wersji libgadu, kopiując przy okazji nieco kodu z libpurple. Od tego czasu utrzymywaniem tego forka zajmował się Tomasz, ale od następnej wersji libgadu prawdopodobnie będę to robił ja. Różnice między oryginalnym libgadu a naszym forkiem są dość spore i w wielu miejscach nadmiarowe, ale kompiluje się on i działa nawet pod MSVC. Pozdrawiam, Bartosz [1] http://www.kadu.net/~dorr/libgadu-win32/index.html ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] Wysyłanie avatarów i OAuth
W dniu 19 października 2011 00:53 użytkownik Tomasz Wasilczyk tomkiewicz.gro...@gmail.com napisał: W dniu 18 października 2011 23:37 użytkownik Wojtek Kaniewski wojte...@toxygen.net napisał: Dnia 2011-10-13, czw o godzinie 03:22 +0200, Tomasz Wasilczyk pisze: Pytanie pierwsze: czy libgadu nie powinno udostępniać możliwości ustawiania avatarów? Czy może każdy klient ma sobie sam to implementować? Jeśli jest taka możliwość, to byłoby świetnie. Spróbuję się tym zająć (niekoniecznie teraz), praktycznie wszystko jest już rozpracowane, trzeba to tylko zaimplementować. Rozumiem, że mogę korzystać z zawartości test/manual/lib? W jednym miejscu w kodzie widziałem zakomentowany fragment, który chyba po zalogowaniu usuwał hasło z pamięci. Rozumiem, że to już nie będzie tak działać? Bo hasło będzie potrzebne do autoryzacji OAuth (która jest ważna godzinę). To było tak dawno temu, że nie pamiętam nawet. Oczywiście można zrobić z tego opcjonalną zależność -- jeśli ktoś nie ma expat i nie interesują go avatary, bo robi konsolową aplikację, nie zmuszajmy go do niczego. A nie lepiej od libxml2? Zgaduję, że będzie to łatwo przepisać, szczególnie że w libxml2 jest wsparcie dla xpath. Libexpat wygląda na nie rozwijane (ostatni update 4 lata temu) i chyba niewiele osób to ma (ja nie miałem, mimo że instaluję libki jak leci). No i oczywiście jeśli będzie już expat, można się zmierzyć też z pobieraniem avatarów. Pidgin to już obsługuje, pewnie nie będzie dużego problemu przenieść. W razie czego zgłaszam gotowość do testowania, pisania kodu, dokumentacji etc. Kadu również jest potencjalnie zainteresowane przeniesieniem obsługi avatarów na bibliotekę. Pozdrawiam, Bartosz ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] Nieprawidłowe działanie gg_vsaprintf w niektórych konfiguracjach
W dniu 11 października 2011 20:46 użytkownik Wojtek Kaniewski wojte...@toxygen.net napisał: - zastanawiam się, po co kopiować zmienną ap do aq (zresztą jak nie ma dostępnych funkcji do kopiowania, nasza funkcja tego po prostu nie robi); Poza tym wywołanie vsnprintf na końcu w wersji patcha C jest prawdopodobnie zbędne (bo i tak w buforze jest to, co trzeba) Jeśli dobrze pamiętam, to na jakimś PowerPC można było użyć typu va_list tylko raz, dlatego jedna kopia była używana do określenia rozmiaru bufora, druga do właściwego vsnprintf(). Nie wiem, czy jest sens nadal utrzymywać taki kod. Przyznam, że nie chciało mi się analizować zbyt szczegółowo tego kawałka kodu, ale zacytuję fragment standardu C99: The object ap may be passed as an argument to another function; if that function invokes the va_arg macro with parameter ap, the value of ap in the calling function is indeterminate and shall be passed to the va_end macro prior to any further reference to ap.[221)] 221) It is permitted to create a pointer to a va_list and pass that pointer to another function, in which case the original function may make further use of the original list after the other function returns. Pozdrawiam ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] API do wysyłania wiadomości HTML
W dniu 6 września 2011 03:15 użytkownik Bartosz Brachaczek b.brachac...@gmail.com napisał: Cześć, Myślę, że przyszedł czas, aby libgadu mogło umożliwiać wysyłanie wiadomości poprzez podanie bezpośrednio treści. Dzięki temu klienty będą mogły całkiem zapomnieć o starych atrybutach formatowania, a także obsługiwać bardziej szczegółowe formatowanie, jeśli taka będzie wola ich developerów. Oczywiście zgłaszam się jako ochotnik do implementacji, zresztą zdaje mi się, że to będzie bardzo łatwe. Chciałbym tylko ustalić, jak to API ma wyglądać. Myślałem o dodaniu takich dwóch funkcji, oczywiście nie zmieniając zachowania istniejących: int gg_send_message_html(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message); int gg_send_message_confer_html(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message); Celowo nie używam sufiksów _xhtml, mimo że struktura gg_event_msg ma pole xhtml_message. Po prostu trudno mi nazywać XHTML-em coś, czemu do poprawnego XML-a trochę brakuje, patrz tagi br i img No ale oczywiście nie ja tutaj o API decyduję i upierał się przy swoim nie będę ;). Zastanawiałem się również przez moment nad umożliwieniem podawania przez klienta niezależnie treści wiadomości HTML oraz czystego tekstu wraz z atrybutami formatowania. Na razie nie widzę jednak potencjalnych użytkowników takiej funkcji, więc się z tym wstrzymuję. Co o tym myślicie? Odzewu nie było (milczenie oznacza zgodę?), ale jako że Wojtek dał mi w międzyczasie dostęp do repo, pozwoliłem sobie wrzucić te zmiany. Pozdrawiam, Bartosz ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
[libgadu-devel] Powtarzające się SIGABRT w teście connect
Witam, Ostatnio zauważyłem, że na moim systemie test connect w losowym momencie dostaje SIGABRT z glibc. Problem udało mi się powtórzyć na kilku systemach (nie na wszystkich). Co ciekawe, pod valgrindem nie mogłem powtórzyć tego problemu. Za to na wszystkich systemach, jakie sprawdzałem, uruchomienie pod kontrolą DUMA[1] dawało SIGSEGV na samym początku testu. Załączam łatę, która sprawia, że nie potrafię więcej powtórzyć tego problemu. Nie mam wielkiego pojęcia na temat działania tego testu, a na temat libgcrypt w ogóle - to, co napisałem, powstało na podstawie fragmentu dokumentacji GnuTLS i nie ręczę za prawidłowość tego kodu ;). Załączam również backtrace z SIGSEGV złapanego po kontrolą DUMA. W normalnych warunkach również crasha miałem w realloc. Pozdrawiam, Bartosz [1] http://sourceforge.net/projects/duma/ diff --git a/test/automatic/connect.c b/test/automatic/connect.c index 0424ac1..03b80c9 100644 --- a/test/automatic/connect.c +++ b/test/automatic/connect.c @@ -83,6 +83,7 @@ static char *log_buffer; /** Local ports */ static int ports[PORT_COUNT]; +static pthread_mutex_t *mutex; static gnutls_certificate_credentials_t x509_cred; static gnutls_dh_params_t dh_params; #define DH_BITS 1024 @@ -101,7 +102,11 @@ static test_param_t *get_test_param(void) static void debug_handler(int level, const char *format, va_list ap) { char buf[4096], *tmp; - int len = (log_buffer) ? strlen(log_buffer) : 0; + size_t len; + + gcry_pthread_mutex_lock((void**) mutex); + + len = (log_buffer) ? strlen(log_buffer) : 0; if (vsnprintf(buf, sizeof(buf), format, ap) = sizeof(buf)) { fprintf(stderr, Increase temporary log buffer size!\n); @@ -115,6 +120,8 @@ static void debug_handler(int level, const char *format, va_list ap) log_buffer = tmp; strcpy(log_buffer + len, buf); + + gcry_pthread_mutex_unlock((void**) mutex); } static inline void set32(char *ptr, unsigned int value) @@ -795,7 +802,9 @@ int main(int argc, char **argv) pthread_t t; gcry_control(GCRYCTL_SET_THREAD_CBS, gcry_threads_pthread); + gcry_check_version(NULL); gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0); + gcry_pthread_mutex_init((void**) mutex); gnutls_global_init(); gnutls_certificate_allocate_credentials(x509_cred); @@ -1010,5 +1019,7 @@ int main(int argc, char **argv) gnutls_dh_params_deinit(dh_params); gnutls_global_deinit(); + gcry_pthread_mutex_destroy((void**) mutex); + return exit_code; } GNU gdb (Gentoo 7.3.1 p1) 7.3.1 Copyright (C) 2011 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type show copying and show warranty for details. This GDB was configured as x86_64-pc-linux-gnu. For bug reporting instructions, please see: http://bugs.gentoo.org/... Reading symbols from /home/beevvy/libgadu-git/test/automatic/.libs/connect...done. (gdb) run Starting program: /home/beevvy/libgadu-git/test/automatic/.libs/connect DUMA 2.5.15 (shared library, NO_LEAKDETECTION) Copyright (C) 2006 Michael Eddington medding...@gmail.com Copyright (C) 2002-2008 Hayati Ayguen h_ayg...@web.de, Procitec GmbH Copyright (C) 1987-1999 Bruce Perens br...@perens.com [Thread debugging using libthread_db enabled] DUMA 2.5.15 (shared library, NO_LEAKDETECTION) Copyright (C) 2006 Michael Eddington medding...@gmail.com Copyright (C) 2002-2008 Hayati Ayguen h_ayg...@web.de, Procitec GmbH Copyright (C) 1987-1999 Bruce Perens br...@perens.com [New Thread 0x7fffef74d700 (LWP 25452)] Test 1 of 648...[New Thread 0x7fffeed4c700 (LWP 25453)] Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 0x7fffeed4c700 (LWP 25453)] 0x77bcfab0 in _duma_memcpy (dest=0x7fffeed7e000, src=0x7fffeed72000, size=214) at duma.c:2207 2207duma.c: Nie ma takiego pliku ani katalogu. in duma.c (gdb) bt full #0 0x77bcfab0 in _duma_memcpy (dest=0x7fffeed7e000, src=0x7fffeed72000, size=214) at duma.c:2207 d = 0x7fffeed7e000 s = 0x7fffeed72000 ** gg_login(0x7fffd3f0: [uin=1, async=1, ...]);\n** gg_watch_fd(0x7fffeed68000);\n// gg_watch_fd() GG_STATE_RESOLVE_HUB_ASYNC\n** gg_resolver_pthread_start(0x7fffeed68000, 0x7fffeed680b8, \appmsg.gad... i = 0 #1 0x77bcff55 in memcpy (dest=0x7fffeed7e000, src=0x7fffeed72000, size=214) at duma.c:2444 No locals. #2 0x77bcf857 in _duma_realloc (oldBuffer=0x7fffeed72000, newSize=258) at duma.c:2111 slot = 0x7fffeef30670 ptr = 0x7fffeed7e000 duma_tls = 0x77dd92f0 #3 0x77bcfef4 in realloc (oldBuffer=0x7fffeed72000, newSize=258) at duma.c:2426 No locals. #4 0x004023a8 in debug_handler (level=16, format=0x779c4bc8 // gg_resolver_run(%d, %s)\n, ap=0x7fffeed4bd70) at
Re: [libgadu-devel] Kodowanie zaszyfrowanych wiadomosci
W dniu 3 września 2010 22:54 użytkownik Jakub Zawadzki darkja...@darkjames.ath.cx napisał: Witam, Nieoficjalnym standardem[1] szyfrowania wiadomości w gg jest wykorzystanie kluczy RSA w kodowaniu WINDOWS-1250. W ekg2 jak implementowaliśmy obsługę UTF-8 w gg, niechcący zmieniliśmy również kodowanie szyfrowanej wiadomości ;) Zastanawiam się czy w pozostałych projektach nastąpiła podobna zmiana a jeśli nie to na ile chętni bylibyście ją przeprowadzić? Jeśli chcemy (a miłoby było) zachować kompatylibność ze starymi klientami. To w nagłówku sim_message_header jest pole 'flags' w których można by zachować informacje o kodowaniu. Ktoś może wie które bity z niego są używane? #v+ typedef struct { unsigned char init[8]; uint16_t magic; /* SIM_MAGIC_V1 0x2391 */ uint8_t flags; } sim_message_header; #v- [1] http://ekg.chmurka.net/docs/sim.txt ekg,ekg2,Kadu,PowerGG ktoś jeszcze? Cześć, Odnalazłem tę trochę starą wiadomość i stwierdzam, że Kadu jest bardzo zainteresowane obsługą UTF-8 w szyfrowaniu sim. Pole 'flags' jest przez ekg, ekg2 i Kadu (tyle sprawdziłem) w ogóle nieużywane, ale memset zapewnia jego wartość równą 0. Korzystając z wolnego czasu zrobiłem wstępną implementację w Kadu[1] i z moich testów wynika, że działa to całkiem sprawnie i zachowuje kompatybilność ze starymi wersjami. Moja propozycja flag jest taka: /* Flaga oznaczająca, że potrafimy przyjąć wiadomość UTF-8. Ustawiamy zawsze. */ #define SIM_FLAG_SUPPORT_UTF8 0x01 /* Flaga oznaczająca, że wiadomość, którą właśnie wysyłamy, jest zakodowana w UTF-8. Powinniśmy jej używać po otrzymaniu od rozmówcy wiadomości z flagą SIM_FLAG_SUPPORT_UTF8. */ #define SIM_FLAG_UTF8_MESSAGE 0x02 Kadu zapamiętuje, czy dany rozmówca wspiera UTF-8 również pomiędzy uruchomieniami programu, ale nie jest to funkcja konieczna ani nawet szczególnie istotna. Pozdrawiam, Bartosz [1] branch simlite-utf8, istotne commity: http://gitorious.org/kadu/kadu/commit/18a1f5c http://gitorious.org/kadu/kadu/commit/8c33c9a ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
[libgadu-devel] API do wysyłania wiadomości HTML
Cześć, Myślę, że przyszedł czas, aby libgadu mogło umożliwiać wysyłanie wiadomości poprzez podanie bezpośrednio treści. Dzięki temu klienty będą mogły całkiem zapomnieć o starych atrybutach formatowania, a także obsługiwać bardziej szczegółowe formatowanie, jeśli taka będzie wola ich developerów. Oczywiście zgłaszam się jako ochotnik do implementacji, zresztą zdaje mi się, że to będzie bardzo łatwe. Chciałbym tylko ustalić, jak to API ma wyglądać. Myślałem o dodaniu takich dwóch funkcji, oczywiście nie zmieniając zachowania istniejących: int gg_send_message_html(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message); int gg_send_message_confer_html(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message); Celowo nie używam sufiksów _xhtml, mimo że struktura gg_event_msg ma pole xhtml_message. Po prostu trudno mi nazywać XHTML-em coś, czemu do poprawnego XML-a trochę brakuje, patrz tagi br i img No ale oczywiście nie ja tutaj o API decyduję i upierał się przy swoim nie będę ;). Zastanawiałem się również przez moment nad umożliwieniem podawania przez klienta niezależnie treści wiadomości HTML oraz czystego tekstu wraz z atrybutami formatowania. Na razie nie widzę jednak potencjalnych użytkowników takiej funkcji, więc się z tym wstrzymuję. Co o tym myślicie? Pozdrawiam, Bartosz ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
[libgadu-devel] [PATCH] Popraw zachowanie funkcji gg_message_html_to_text() na architekturach big endian
Co prawda nie mam żadnego doświadczenia z architekturami big endian i nie testowałem na takiej maszynie, ale ta poprawka wydaje mi się w porządku. W każdym razie wydaje się nie psuć niczego na little endian. Nie użyłem funkcji gg_fix16(), aby plik message.c pozostał niezależny od zewnętrznego kodu. Zresztą funkcja gg_message_text_to_html() już wcześniej używała podobnego sposobu jak tutaj do uniknięcia problemów z endianowościa: /* ... */ attr_pos = format[format_idx] | (format[format_idx + 1] 8); /* ... */ --- src/message.c | 15 ++- 1 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/message.c b/src/message.c index 83685d4..d9b4105 100644 --- a/src/message.c +++ b/src/message.c @@ -617,10 +617,14 @@ static void gg_after_append_formatted_char(uint16_t *pos, unsigned char attr_fla *format -= imgs_size; memmove(*format + attr_size, *format, imgs_size); - memcpy(*format, pos, sizeof(*pos)); - *format += sizeof(*pos); - memcpy(*format, attr_flag, sizeof(attr_flag)); - *format += sizeof(attr_flag); + **format = (unsigned char) (*pos (uint16_t) 0x00ffU); + *format += 1; + **format = (unsigned char) ((*pos (uint16_t) 0xff00U) 8); + *format += 1; + + **format = attr_flag; + *format += 1; + if (has_color) { memcpy(*format, color, color_size); *format += color_size; @@ -717,7 +721,8 @@ size_t gg_message_html_to_text(char *dst, unsigned char *format, size_t *format_ if (format != NULL) { char buf[3] = {}; - memcpy(img_attr, pos, sizeof(pos)); + img_attr[0] = (unsigned char) (pos (uint16_t) 0x00ffU); + img_attr[1] = (unsigned char) ((pos (uint16_t) 0xff00U) 8); img_attr[2] = GG_FONT_IMAGE; img_attr[3] = '\x09'; img_attr[4] = '\x01'; -- 1.7.6.1 ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
[libgadu-devel] [PATCH] Zamiana kilku magic numbers na istniejące makrodefinicje
--- src/libgadu.c | 10 +- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libgadu.c b/src/libgadu.c index fe69daa..aec389c 100644 --- a/src/libgadu.c +++ b/src/libgadu.c @@ -1475,7 +1475,7 @@ int gg_send_message_confer_richtext(struct gg_session *sess, int msgclass, int r } if (recipients_count 1) { - r.flag = 0x01; + r.flag = GG_MSG_OPTION_CONFERENCE; r.count = gg_fix32(recipients_count - 1); recps = malloc(sizeof(uin_t) * recipients_count); @@ -1613,7 +1613,7 @@ int gg_image_request(struct gg_session *sess, uin_t recipient, int size, uint32_ s.seq = gg_fix32(0); s.msgclass = gg_fix32(GG_CLASS_MSG); - r.flag = 0x04; + r.flag = GG_MSG_OPTION_IMAGE_REQUEST; r.size = gg_fix32(size); r.crc32 = gg_fix32(crc32); @@ -1712,7 +1712,7 @@ int gg_image_reply(struct gg_session *sess, uin_t recipient, const char *filenam buf[0] = 0; r = (void*) buf[1]; - r-flag = 0x05; + r-flag = GG_MSG_OPTION_IMAGE_REPLY; r-size = gg_fix32(size); r-crc32 = gg_fix32(gg_crc32(0, (const unsigned char*) image, size)); @@ -1723,7 +1723,7 @@ int gg_image_reply(struct gg_session *sess, uin_t recipient, const char *filenam buflen = sizeof(struct gg_msg_image_reply) + 1; /* w pierwszym kawałku jest nazwa pliku */ - if (r-flag == 0x05) { + if (r-flag == GG_MSG_OPTION_IMAGE_REPLY) { strcpy(buf + buflen, filename); buflen += strlen(filename) + 1; } @@ -1739,7 +1739,7 @@ int gg_image_reply(struct gg_session *sess, uin_t recipient, const char *filenam if (res == -1) break; - r-flag = 0x06; + r-flag = GG_MSG_OPTION_IMAGE_REPLY_MORE; } return res; -- 1.7.6.1 ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
[libgadu-devel] [PATCH 01/14] Usunięcie niepotrzebnej zmiennej
--- src/handlers.c |6 ++ 1 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/handlers.c b/src/handlers.c index bc442e8..0377937 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -790,7 +790,6 @@ static int gg_session_handle_recv_msg(struct gg_session *sess, uint32_t type, co const struct gg_recv_msg *r = (const struct gg_recv_msg*) packet; const char *payload = packet + sizeof(struct gg_recv_msg); const char *payload_end = packet + length; - char *tmp; gg_debug_session(sess, GG_DEBUG_FUNCTION, ** gg_handle_recv_msg(%p, %d, %p);\n, packet, length, e); @@ -834,10 +833,9 @@ static int gg_session_handle_recv_msg(struct gg_session *sess, uint32_t type, co e-event.msg.time = gg_fix32(r-time); e-event.msg.seq = gg_fix32(r-seq); - tmp = gg_encoding_convert(payload, GG_ENCODING_CP1250, sess-encoding, length, -1); - if (tmp == NULL) + e-event.msg.message = (unsigned char*) gg_encoding_convert(payload, GG_ENCODING_CP1250, sess-encoding, length, -1); + if (e-event.msg.message == NULL) goto fail; - e-event.msg.message = (unsigned char*) tmp; gg_session_send_msg_ack(sess, gg_fix32(r-seq)); return 0; -- 1.7.6.1 ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
[libgadu-devel] [PATCH 02/14] Bardziej zwracamy uwagę na niepowodzenia w alokacji pamięci
--- src/handlers.c | 27 +++ 1 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/handlers.c b/src/handlers.c index 0377937..9100e1b 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -834,8 +834,10 @@ static int gg_session_handle_recv_msg(struct gg_session *sess, uint32_t type, co e-event.msg.seq = gg_fix32(r-seq); e-event.msg.message = (unsigned char*) gg_encoding_convert(payload, GG_ENCODING_CP1250, sess-encoding, length, -1); - if (e-event.msg.message == NULL) + if (e-event.msg.message == NULL) { + gg_debug_session(sess, GG_DEBUG_MISC, // gg_session_handle_recv_msg() out of memory\n); goto fail; + } gg_session_send_msg_ack(sess, gg_fix32(r-seq)); return 0; @@ -923,6 +925,11 @@ static int gg_session_handle_recv_msg_80(struct gg_session *sess, uint32_t type, if (sess-encoding == GG_ENCODING_CP1250) { e-event.msg.message = (unsigned char*) strdup(packet + offset_plain); + + if (e-event.msg.message == NULL) { + gg_debug_session(sess, GG_DEBUG_MISC, // gg_session_handle_recv_msg_80() out of memory\n); + goto fail; + } } else { if (offset_plain sizeof(struct gg_recv_msg80)) { int len; @@ -930,18 +937,30 @@ static int gg_session_handle_recv_msg_80(struct gg_session *sess, uint32_t type, len = gg_message_html_to_text(NULL, packet + sizeof(struct gg_recv_msg80)); e-event.msg.message = malloc(len + 1); - if (e-event.msg.message == NULL) + if (e-event.msg.message == NULL) { + gg_debug_session(sess, GG_DEBUG_MISC, // gg_session_handle_recv_msg_80() out of memory\n); goto fail; + } gg_message_html_to_text((char*) e-event.msg.message, packet + sizeof(struct gg_recv_msg80)); } else { e-event.msg.message = (unsigned char*) gg_encoding_convert(packet + offset_plain, GG_ENCODING_CP1250, sess-encoding, -1, -1); + + if (e-event.msg.message == NULL) { + gg_debug_session(sess, GG_DEBUG_MISC, // gg_session_handle_recv_msg_80() out of memory\n); + goto fail; + } } } - if (offset_plain sizeof(struct gg_recv_msg80)) + if (offset_plain sizeof(struct gg_recv_msg80)) { e-event.msg.xhtml_message = gg_encoding_convert(packet + sizeof(struct gg_recv_msg80), GG_ENCODING_UTF8, sess-encoding, -1, -1); - else + + if (e-event.msg.xhtml_message == NULL) { + gg_debug_session(sess, GG_DEBUG_MISC, // gg_session_handle_recv_msg_80() out of memory\n); + goto fail; + } + } else e-event.msg.xhtml_message = NULL; gg_session_send_msg_ack(sess, gg_fix32(r-seq)); -- 1.7.6.1 ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
[libgadu-devel] [PATCH 06/14] Dla każdego znaku sprawdzamy wszystkie atrybuty formatowania
Ostatni z dodanych testów pokazuje dlaczego ta zmiana była konieczna. Krótko mówiąc, oryginalny klient wcale nie gwarantuje, że prześle atrybuty formatowania posortowane niemalejąco według pozycji w tekście, jak do tej pory zakładaliśmy. --- src/message.c | 79 +++-- test/automatic/message2.c |8 - 2 files changed, 47 insertions(+), 40 deletions(-) diff --git a/src/message.c b/src/message.c index d849750..125cc72 100644 --- a/src/message.c +++ b/src/message.c @@ -392,36 +392,25 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin const char img_fmt[] = img name=\%02x%02x%02x%02x%02x%02x%02x%02x\; const size_t img_len = 29; size_t char_pos = 0; - size_t format_idx = 0; unsigned char old_attr = 0; const unsigned char *color = (const unsigned char*) \x00\x00\x00; + int in_span = 0; unsigned int i; - size_t len; + size_t len = 0; const unsigned char *format_ = (const unsigned char*) format; - len = 0; - - /* Nie mamy atrybutów dla pierwsze znaku, a tekst nie jest pusty, więc -* tak czy inaczej trzeba otworzyć span. */ - - if (src[0] != 0 (format_idx + 3 format_len || (format_[format_idx] | (format_[format_idx + 1] 8)) != 0)) { - if (dst != NULL) - sprintf(dst[len], span_fmt, 0, 0, 0); - - len += span_len; - } - /* Pętla przechodzi też przez kończące \0, żeby móc dokleić obrazek * na końcu tekstu. */ for (i = 0; ; i++) { int in_char = 0; + size_t format_idx = 0; /* Sprawdź, czy bajt jest kontynuacją znaku UTF-8. */ if (encoding == GG_ENCODING_UTF8 (src[i] 0xc0) == 0x80) in_char = 1; - /* Analizuj atrybuty tak długo jak dotyczą aktualnego znaku. */ + /* Analizuj wszystkie atrybuty dotyczące aktualnego znaku. */ for (;;) { unsigned char attr; size_t attr_pos; @@ -434,10 +423,6 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin break; attr_pos = format_[format_idx] | (format_[format_idx + 1] 8); - - if (attr_pos != char_pos) - break; - attr = format_[format_idx + 2]; /* Nie doklejaj atrybutów na końcu, co najwyżej obrazki. */ @@ -447,19 +432,28 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin format_idx += 3; - if ((attr (GG_FONT_BOLD | GG_FONT_ITALIC | GG_FONT_UNDERLINE | GG_FONT_COLOR)) != 0 || (attr == 0 old_attr != 0)) { - if (char_pos != 0) { - if ((old_attr GG_FONT_UNDERLINE) != 0) - gg_append(dst, len, /u, 4); + if (attr_pos != char_pos) { + if ((attr GG_FONT_COLOR) != 0) + format_idx += 3; + if ((attr GG_FONT_IMAGE) != 0) + format_idx += 10; + + continue; + } - if ((old_attr GG_FONT_ITALIC) != 0) - gg_append(dst, len, /i, 4); + if ((old_attr GG_FONT_UNDERLINE) != 0) + gg_append(dst, len, /u, 4); - if ((old_attr GG_FONT_BOLD) != 0) - gg_append(dst, len, /b, 4); + if ((old_attr GG_FONT_ITALIC) != 0) + gg_append(dst, len, /i, 4); - if (src[i] != 0) - gg_append(dst, len, /span, 7); + if ((old_attr GG_FONT_BOLD) != 0) + gg_append(dst, len, /b, 4); + + if ((attr (GG_FONT_BOLD | GG_FONT_ITALIC | GG_FONT_UNDERLINE | GG_FONT_COLOR)) != 0 || (attr == 0 old_attr != 0)) { + if (in_span) { + gg_append(dst, len, /span, 7); + in_span = 0; } if (((attr GG_FONT_COLOR) != 0) (format_idx + 3 = format_len)) { @@ -472,12 +466,10 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin if (src[i] != 0) { if (dst != NULL)
[libgadu-devel] [PATCH 03/14] Pozwalamy przekazać tekst w CP1250 do funkcji gg_message_text_to_html
--- include/message.h |2 +- src/libgadu.c |4 ++-- src/message.c | 11 ++- test/automatic/message2.c |4 ++-- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/include/message.h b/include/message.h index 824f1a8..9d02baf 100644 --- a/include/message.h +++ b/include/message.h @@ -51,6 +51,6 @@ int gg_message_init(gg_message_t *gm, int msgclass, int seq, uin_t *recipients, #endif size_t gg_message_html_to_text(char *dst, const char *html); -size_t gg_message_text_to_html(char *dst, const char *utf_msg, const char *format, size_t format_len); +size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encoding, const char *format, size_t format_len); #endif /* LIBGADU_MESSAGE_H */ diff --git a/src/libgadu.c b/src/libgadu.c index aec389c..7084267 100644 --- a/src/libgadu.c +++ b/src/libgadu.c @@ -1457,7 +1457,7 @@ int gg_send_message_confer_richtext(struct gg_session *sess, int msgclass, int r formatlen = 9; } - len = gg_message_text_to_html(NULL, utf_msg, (const char*) format + 3, formatlen - 3); + len = gg_message_text_to_html(NULL, utf_msg, GG_ENCODING_UTF8, (const char*) format + 3, formatlen - 3); html_msg = malloc(len + 1); @@ -1466,7 +1466,7 @@ int gg_send_message_confer_richtext(struct gg_session *sess, int msgclass, int r goto cleanup; } - gg_message_text_to_html(html_msg, utf_msg, (const char*) format + 3, formatlen - 3); + gg_message_text_to_html(html_msg, utf_msg, GG_ENCODING_UTF8, (const char*) format + 3, formatlen - 3); s80.seq = gg_fix32(seq_no); s80.msgclass = gg_fix32(msgclass); diff --git a/src/message.c b/src/message.c index 222fe65..d06da5f 100644 --- a/src/message.c +++ b/src/message.c @@ -292,14 +292,14 @@ const char *gg_message_get_html(gg_message_t *gm) free(gm-html_converted); - len = gg_message_text_to_html(NULL, gm-text, gm-attributes, gm-attributes_length); + len = gg_message_text_to_html(NULL, gm-text, GG_ENCODING_UTF8, gm-attributes, gm-attributes_length); gm-html_converted = malloc(len + 1); if (gm-html_converted == NULL) return NULL; - gg_message_text_to_html(gm-html_converted, gm-text, gm-attributes, gm-attributes_length); + gg_message_text_to_html(gm-html_converted, gm-text, GG_ENCODING_UTF8, gm-attributes, gm-attributes_length); return gm-html_converted; } @@ -373,7 +373,8 @@ static void gg_append(char *dst, size_t *pos, const void *src, int len) * \internal Zamienia tekst z formatowaniem Gadu-Gadu na HTML. * * \param dst Bufor wynikowy (może być \c NULL) - * \param src Tekst źródłowy w UTF-8 + * \param src Tekst źródłowy + * \param encoding Kodowanie tekstu źródłowego oraz wynikowego * \param format Atrybuty tekstu źródłowego * \param format_len Długość bloku atrybutów tekstu źródłowego * @@ -384,7 +385,7 @@ static void gg_append(char *dst, size_t *pos, const void *src, int len) * * \return Długość tekstu wynikowego bez \c \\0 (nawet jeśli \c dst to \c NULL). */ -size_t gg_message_text_to_html(char *dst, const char *src, const char *format, size_t format_len) +size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encoding, const char *format, size_t format_len) { const char span_fmt[] = span style=\color:#%02x%02x%02x; font-family:'MS Shell Dlg 2'; font-size:9pt; \; const size_t span_len = 75; @@ -530,7 +531,7 @@ size_t gg_message_text_to_html(char *dst, const char *src, const char *format, s /* Sprawdź, czy bajt nie jest kontynuacją znaku unikodowego. */ - if ((src[i] 0xc0) != 0xc0) + if (encoding != GG_ENCODING_UTF8 || (src[i] 0xc0) != 0xc0) char_pos++; if (src[i] == 0) diff --git a/test/automatic/message2.c b/test/automatic/message2.c index 722972b..53b2ce1 100644 --- a/test/automatic/message2.c +++ b/test/automatic/message2.c @@ -138,7 +138,7 @@ static void test_text_to_html(const char *input, const char *attr, size_t attr_l xmlDocPtr doc; #endif - len = gg_message_text_to_html(NULL, input, attr, attr_len); + len = gg_message_text_to_html(NULL, input, GG_ENCODING_UTF8, attr, attr_len); result = malloc(len + 1); @@ -147,7 +147,7 @@ static void test_text_to_html(const char *input, const char *attr, size_t attr_l exit(1); } - gg_message_text_to_html(result, input, attr, attr_len); + gg_message_text_to_html(result, input, GG_ENCODING_UTF8, attr, attr_len); printf(text: \%s\, input); if (attr != NULL) { -- 1.7.6.1 ___ libgadu-devel
[libgadu-devel] [PATCH 07/14] Mała zmiana w radzeniu sobie z domyślnym kolorem wiadomości
--- src/message.c |8 +--- 1 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/message.c b/src/message.c index 125cc72..7fc2145 100644 --- a/src/message.c +++ b/src/message.c @@ -393,7 +393,7 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin const size_t img_len = 29; size_t char_pos = 0; unsigned char old_attr = 0; - const unsigned char *color = (const unsigned char*) \x00\x00\x00; + const unsigned char default_color[] = {'\x00', '\x00', '\x00'}; int in_span = 0; unsigned int i; size_t len = 0; @@ -451,6 +451,8 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin gg_append(dst, len, /b, 4); if ((attr (GG_FONT_BOLD | GG_FONT_ITALIC | GG_FONT_UNDERLINE | GG_FONT_COLOR)) != 0 || (attr == 0 old_attr != 0)) { + const unsigned char *color; + if (in_span) { gg_append(dst, len, /span, 7); in_span = 0; @@ -460,7 +462,7 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin color = format_[format_idx]; format_idx += 3; } else { - color = (const unsigned char*) \x00\x00\x00; + color = default_color; } if (src[i] != 0) { @@ -509,7 +511,7 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin if (!in_span) { if (dst != NULL) - sprintf(dst[len], span_fmt, 0, 0, 0); + sprintf(dst[len], span_fmt, default_color[0], default_color[1], default_color[2]); len += span_len; in_span = 1; -- 1.7.6.1 ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
[libgadu-devel] [PATCH 04/14] Dla wiadomości przychodzących zawsze ustawiamy pole xhtml_message
W razie potrzeby konwertujemy przychodzącą wiadomość w czystym tekście do HTML-a. --- src/handlers.c | 31 --- 1 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/handlers.c b/src/handlers.c index 9100e1b..764c5a0 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -790,6 +790,7 @@ static int gg_session_handle_recv_msg(struct gg_session *sess, uint32_t type, co const struct gg_recv_msg *r = (const struct gg_recv_msg*) packet; const char *payload = packet + sizeof(struct gg_recv_msg); const char *payload_end = packet + length; + size_t len; gg_debug_session(sess, GG_DEBUG_FUNCTION, ** gg_handle_recv_msg(%p, %d, %p);\n, packet, length, e); @@ -828,6 +829,7 @@ static int gg_session_handle_recv_msg(struct gg_session *sess, uint32_t type, co } e-type = GG_EVENT_MSG; + memset(e-event, 0, sizeof(e-event)); e-event.msg.msgclass = gg_fix32(r-msgclass); e-event.msg.sender = gg_fix32(r-sender); e-event.msg.time = gg_fix32(r-time); @@ -839,11 +841,22 @@ static int gg_session_handle_recv_msg(struct gg_session *sess, uint32_t type, co goto fail; } + len = gg_message_text_to_html(NULL, (char*) e-event.msg.message, sess-encoding, e-event.msg.formats, e-event.msg.formats_length); + e-event.msg.xhtml_message = malloc(len + 1); + + if (e-event.msg.xhtml_message == NULL) { + gg_debug_session(sess, GG_DEBUG_MISC, // gg_session_handle_recv_msg() out of memory\n); + goto fail; + } + + gg_message_text_to_html(e-event.msg.xhtml_message, (char*) e-event.msg.message, sess-encoding, e-event.msg.formats, e-event.msg.formats_length); + gg_session_send_msg_ack(sess, gg_fix32(r-seq)); return 0; fail: free(e-event.msg.message); + free(e-event.msg.xhtml_message); free(e-event.msg.recipients); free(e-event.msg.formats); return -1; @@ -904,6 +917,7 @@ static int gg_session_handle_recv_msg_80(struct gg_session *sess, uint32_t type, } e-type = (type != GG_RECV_OWN_MSG) ? GG_EVENT_MSG : GG_EVENT_MULTILOGON_MSG; + memset(e-event, 0, sizeof(e-event)); e-event.msg.msgclass = gg_fix32(r-msgclass); e-event.msg.sender = gg_fix32(r-sender); e-event.msg.time = gg_fix32(r-time); @@ -932,7 +946,7 @@ static int gg_session_handle_recv_msg_80(struct gg_session *sess, uint32_t type, } } else { if (offset_plain sizeof(struct gg_recv_msg80)) { - int len; + size_t len; len = gg_message_html_to_text(NULL, packet + sizeof(struct gg_recv_msg80)); e-event.msg.message = malloc(len + 1); @@ -960,8 +974,19 @@ static int gg_session_handle_recv_msg_80(struct gg_session *sess, uint32_t type, gg_debug_session(sess, GG_DEBUG_MISC, // gg_session_handle_recv_msg_80() out of memory\n); goto fail; } - } else - e-event.msg.xhtml_message = NULL; + } else { + size_t len; + + len = gg_message_text_to_html(NULL, (char*) e-event.msg.message, sess-encoding, e-event.msg.formats, e-event.msg.formats_length); + e-event.msg.xhtml_message = malloc(len + 1); + + if (e-event.msg.xhtml_message == NULL) { + gg_debug_session(sess, GG_DEBUG_MISC, // gg_session_handle_recv_msg_80() out of memory\n); + goto fail; + } + + gg_message_text_to_html(e-event.msg.xhtml_message, (char*) e-event.msg.message, sess-encoding, e-event.msg.formats, e-event.msg.formats_length); + } gg_session_send_msg_ack(sess, gg_fix32(r-seq)); return 0; -- 1.7.6.1 ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
[libgadu-devel] [PATCH 09/14] Znaki oznaczone jako GG_FONT_IMAGE nie są częścią wiadomości
--- src/message.c | 14 ++ test/automatic/message2.c | 99 + 2 files changed, 78 insertions(+), 35 deletions(-) diff --git a/src/message.c b/src/message.c index 0cb8ef1..2048934 100644 --- a/src/message.c +++ b/src/message.c @@ -410,6 +410,11 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin if (encoding == GG_ENCODING_UTF8 (src[i] 0xc0) == 0x80) in_char = 1; + /* GG_FONT_IMAGE powinno dotyczyć tylko jednego znaku, więc czyścimy stary atrybut */ + + if (!in_char (old_attr GG_FONT_IMAGE) != 0) + old_attr = ~GG_FONT_IMAGE; + /* Analizuj wszystkie atrybuty dotyczące aktualnego znaku. */ for (;;) { unsigned char attr; @@ -506,6 +511,15 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin if (src[i] == 0) break; + /* Znaki oznaczone jako GG_FONT_IMAGE nie są częścią wiadomości. */ + + if ((old_attr GG_FONT_IMAGE) != 0) { + if (!in_char) + char_pos++; + + continue; + } + /* Jesteśmy na początku tekstu i choć nie było atrybutów dla pierwszego * znaku, ponieważ tekst nie jest pusty, trzeba otworzyć span. */ diff --git a/test/automatic/message2.c b/test/automatic/message2.c index 77505ca..5c34c40 100644 --- a/test/automatic/message2.c +++ b/test/automatic/message2.c @@ -1,5 +1,6 @@ #include stdio.h #include string.h +#include libgadu.h #include message.h #include config.h #ifdef HAVE_LIBXML2 @@ -11,6 +12,7 @@ struct test_data { const char *src; const char *dst; + gg_encoding_t encoding; const char *attr; size_t attr_len; }; @@ -21,82 +23,100 @@ struct test_data const struct test_data text_to_html[] = { /* Typowa wiadomość */ - { bzdura\n\alama'kota\, SPAN(lt;bzduragt;brquot;alaamp;maapos;kotaquot;) }, + { bzdura\n\alama'kota\, SPAN(lt;bzduragt;brquot;alaamp;maapos;kotaquot;), GG_ENCODING_UTF8 }, /* Obrazek na początku tekstu */ - { test, img name=\8877665544332211\ SPAN(test), \x00\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 13 }, + { test, img name=\8877665544332211\ SPAN(test), GG_ENCODING_UTF8, \x00\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 13 }, + + /* Obrazek na początku tekstu, dokładnie tak jak wysyła oryginalny klient */ + { \xa0test, img name=\8877665544332211\ SPAN(test), GG_ENCODING_CP1250, \x01\x00\x08\x00\x00\x00\x00\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 19 }, /* Obrazek na końcu tekstu */ - { test, SPAN(testimg name=\8877665544332211\), \x04\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 13 }, + { test, SPAN(testimg name=\8877665544332211\), GG_ENCODING_UTF8, \x04\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 13 }, + + /* Obrazek na końcu tekstu, dokładnie tak jak wysyła oryginalny klient */ + { test\xa0, SPAN(testimg name=\8877665544332211\), GG_ENCODING_CP1250, \x00\x00\x08\x00\x00\x00\x04\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 19 }, /* Obrazek w środku tekstu */ - { testtest, SPAN(testimg name=\8877665544332211\test), \x04\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 13 }, + { test test, SPAN(testimg name=\8877665544332211\test), GG_ENCODING_UTF8, \x04\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 13 }, - /* Obrazek w środku tekstu, tekst na końcu formatowany, atrybuty w zwykłej kolejności */ - { testtest foo, SPAN(testimg name=\8877665544332211\test ) SPAN(bfoo/b), \x04\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88\x09\x00\x01, 16 }, + /* Obrazek w środku tekstu, tekst na końcu formatowany */ + { test test foo, SPAN(testimg name=\8877665544332211\test ) SPAN(bfoo/b), GG_ENCODING_UTF8, \x04\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88\x0a\x00\x01, 16 }, - /* Obrazek w środku tekstu, tekst na końcu formatowany, atrybuty obrazka na końcu, czyli tak jak wysyła oryginalny klient */ - { testtest foo, SPAN(testimg name=\8877665544332211\test ) SPAN(bfoo/b), \x09\x00\x01\x04\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 16 }, + /* Obrazek w środku tekstu, tekst na końcu formatowany, dokładnie tak jak wysyła oryginalny klient */ + { test\xa0test foo, SPAN(testimg name=\8877665544332211\) SPAN(test ) SPAN(bfoo/b), GG_ENCODING_CP1250, \x00\x00\x08\x00\x00\x00\x05\x00\x08\x00\x00\x00\x0a\x00\x09\x00\x00\x00\x04\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 31 }, /* Obrazek poza tekstem */ - { test, SPAN(test), \x05\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 13 }, + { test, SPAN(test), GG_ENCODING_UTF8,
[libgadu-devel] [PATCH 11/14] Zmiana typu argumentu attr gg_message_text_to_html() na const unsigned char* oraz usunięcie zbędnej zmiennej
--- include/message.h |2 +- src/libgadu.c |4 ++-- src/message.c | 25 - test/automatic/message2.c |4 ++-- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/include/message.h b/include/message.h index 9d02baf..ced7f9a 100644 --- a/include/message.h +++ b/include/message.h @@ -51,6 +51,6 @@ int gg_message_init(gg_message_t *gm, int msgclass, int seq, uin_t *recipients, #endif size_t gg_message_html_to_text(char *dst, const char *html); -size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encoding, const char *format, size_t format_len); +size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encoding, const unsigned char *format, size_t format_len); #endif /* LIBGADU_MESSAGE_H */ diff --git a/src/libgadu.c b/src/libgadu.c index 7084267..c59f499 100644 --- a/src/libgadu.c +++ b/src/libgadu.c @@ -1457,7 +1457,7 @@ int gg_send_message_confer_richtext(struct gg_session *sess, int msgclass, int r formatlen = 9; } - len = gg_message_text_to_html(NULL, utf_msg, GG_ENCODING_UTF8, (const char*) format + 3, formatlen - 3); + len = gg_message_text_to_html(NULL, utf_msg, GG_ENCODING_UTF8, format + 3, formatlen - 3); html_msg = malloc(len + 1); @@ -1466,7 +1466,7 @@ int gg_send_message_confer_richtext(struct gg_session *sess, int msgclass, int r goto cleanup; } - gg_message_text_to_html(html_msg, utf_msg, GG_ENCODING_UTF8, (const char*) format + 3, formatlen - 3); + gg_message_text_to_html(html_msg, utf_msg, GG_ENCODING_UTF8, format + 3, formatlen - 3); s80.seq = gg_fix32(seq_no); s80.msgclass = gg_fix32(msgclass); diff --git a/src/message.c b/src/message.c index 4b798a8..7d403df 100644 --- a/src/message.c +++ b/src/message.c @@ -385,7 +385,7 @@ static void gg_append(char *dst, size_t *pos, const void *src, int len) * * \return Długość tekstu wynikowego bez \c \\0 (nawet jeśli \c dst to \c NULL). */ -size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encoding, const char *format, size_t format_len) +size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encoding, const unsigned char *format, size_t format_len) { const char span_fmt[] = span style=\color:#%02x%02x%02x; font-family:'MS Shell Dlg 2'; font-size:9pt; \; const size_t span_len = 75; @@ -398,7 +398,6 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin int in_span = 0; unsigned int i; size_t len = 0; - const unsigned char *format_ = (const unsigned char*) format; /* Pętla przechodzi też przez kończące \0, żeby móc dokleić obrazek * na końcu tekstu. */ @@ -428,8 +427,8 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin if (format_idx + 3 format_len) break; - attr_pos = format_[format_idx] | (format_[format_idx + 1] 8); - attr = format_[format_idx + 2]; + attr_pos = format[format_idx] | (format[format_idx + 1] 8); + attr = format[format_idx + 2]; /* Nie doklejaj atrybutów na końcu, co najwyżej obrazki. */ @@ -460,7 +459,7 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin const unsigned char *color; if (((attr GG_FONT_COLOR) != 0) (format_idx + 3 = format_len)) { - color = format_[format_idx]; + color = format[format_idx]; format_idx += 3; } else { color = default_color; @@ -495,14 +494,14 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin if (((attr GG_FONT_IMAGE) != 0) (format_idx + 10 = format_len)) { if (dst != NULL) { sprintf(dst[len], img_fmt, - (unsigned int) format_[format_idx + 9], - (unsigned int) format_[format_idx + 8], - (unsigned int) format_[format_idx + 7], - (unsigned int) format_[format_idx + 6], - (unsigned int) format_[format_idx + 5], - (unsigned int) format_[format_idx + 4], - (unsigned int) format_[format_idx +
[libgadu-devel] [PATCH 12/14] Rozbudowanie funkcji gg_message_html_to_text() o możliwość generowania atrybutów formatowania
--- include/message.h |2 +- src/handlers.c|4 +- src/message.c | 237 + test/automatic/message2.c |4 +- 4 files changed, 222 insertions(+), 25 deletions(-) diff --git a/include/message.h b/include/message.h index ced7f9a..be280b7 100644 --- a/include/message.h +++ b/include/message.h @@ -50,7 +50,7 @@ int gg_message_init(gg_message_t *gm, int msgclass, int seq, uin_t *recipients, #endif -size_t gg_message_html_to_text(char *dst, const char *html); +size_t gg_message_html_to_text(char *dst, unsigned char *format, size_t *format_len, const char *html); size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encoding, const unsigned char *format, size_t format_len); #endif /* LIBGADU_MESSAGE_H */ diff --git a/src/handlers.c b/src/handlers.c index 764c5a0..2e53b70 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -948,7 +948,7 @@ static int gg_session_handle_recv_msg_80(struct gg_session *sess, uint32_t type, if (offset_plain sizeof(struct gg_recv_msg80)) { size_t len; - len = gg_message_html_to_text(NULL, packet + sizeof(struct gg_recv_msg80)); + len = gg_message_html_to_text(NULL, NULL, NULL, packet + sizeof(struct gg_recv_msg80)); e-event.msg.message = malloc(len + 1); if (e-event.msg.message == NULL) { @@ -956,7 +956,7 @@ static int gg_session_handle_recv_msg_80(struct gg_session *sess, uint32_t type, goto fail; } - gg_message_html_to_text((char*) e-event.msg.message, packet + sizeof(struct gg_recv_msg80)); + gg_message_html_to_text((char*) e-event.msg.message, NULL, NULL, packet + sizeof(struct gg_recv_msg80)); } else { e-event.msg.message = (unsigned char*) gg_encoding_convert(packet + offset_plain, GG_ENCODING_CP1250, sess-encoding, -1, -1); diff --git a/src/message.c b/src/message.c index 7d403df..6e755a6 100644 --- a/src/message.c +++ b/src/message.c @@ -361,7 +361,7 @@ int gg_message_get_attributes(gg_message_t *gm, const char **attributes, size_t * \param src Dodawany tekst * \param len Długość dodawanego tekstu */ -static void gg_append(char *dst, size_t *pos, const void *src, int len) +static void gg_append(char *dst, size_t *pos, const void *src, size_t len) { if (dst != NULL) memcpy(dst[*pos], src, len); @@ -589,36 +589,99 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin } /** + * \internal Dokleja nowe atrybuty formatowania, jeśli konieczne, oraz inkrementuje pozycję znaku w tekście. + * + * \param pos Wskaźnik na zmienną przechowującą pozycję znaku w tekście + * \param attr_flag Aktualna flaga atrybutu formatowania + * \param old_attr_flag Wskaźnik na poprzednią flagę atrybutu formatowania + * \param color Wskaźnik na tablicę z aktualnym kolorem RGB (jeśli \p attr_flag nie zawiera flagi \c GG_FONT_COLOR, ignorowane) + * \param old_color Wskaźnik na tablicę z poprzednim kolorem RGB + * \param imgs_size Rozmiar atrybutów formatowania obrazków znajdujących się obecnie w tablicy atrybutów formatowania, w bajtach + * \param format Wskaźnik na wskaźnik do tablicy atrybutów formatowania + * \param format_len Wskaźnik na zmienną zawierającą długość tablicy atrybutów formatowania, w bajtach (może być \c NULL) + */ +static void gg_after_append_formatted_char(uint16_t *pos, unsigned char attr_flag, unsigned char *old_attr_flag, const unsigned char *color, unsigned char *old_color, size_t imgs_size, unsigned char **format, size_t *format_len) +{ + const size_t color_size = 3; + int has_color = 0; + + if ((attr_flag GG_FONT_COLOR) != 0) + has_color = 1; + + if (*old_attr_flag != attr_flag || (has_color memcmp(old_color, color, color_size != 0))) { + size_t attr_size = sizeof(*pos) + sizeof(attr_flag) + (has_color ? color_size : 0); + + if (*format != NULL) { + /* Staramy się naśladować oryginalnego klienta i atrybuty obrazków trzymamy na końcu */ + + *format -= imgs_size; + memmove(*format + attr_size, *format, imgs_size); + + memcpy(*format, pos, sizeof(*pos)); + *format += sizeof(*pos); + memcpy(*format, attr_flag, sizeof(attr_flag)); + *format += sizeof(attr_flag); + if (has_color) { + memcpy(*format, color, color_size); + *format += color_size; + } + + *format += imgs_size; + } + + if (format_len != NULL) + *format_len +=
[libgadu-devel] [PATCH 13/14] Jeśli podmieniamy message, zapewniajmy również własną wersję formats
Dzięki tej zmianie formatowanie w odebranych wiadomościach m.in. od Infobota jest poprawne. --- src/handlers.c| 15 --- test/automatic/script/20-messages.scr | 30 -- 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/src/handlers.c b/src/handlers.c index 2e53b70..962f265 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -946,9 +946,9 @@ static int gg_session_handle_recv_msg_80(struct gg_session *sess, uint32_t type, } } else { if (offset_plain sizeof(struct gg_recv_msg80)) { - size_t len; + size_t len, fmt_len; - len = gg_message_html_to_text(NULL, NULL, NULL, packet + sizeof(struct gg_recv_msg80)); + len = gg_message_html_to_text(NULL, NULL, fmt_len, packet + sizeof(struct gg_recv_msg80)); e-event.msg.message = malloc(len + 1); if (e-event.msg.message == NULL) { @@ -956,7 +956,16 @@ static int gg_session_handle_recv_msg_80(struct gg_session *sess, uint32_t type, goto fail; } - gg_message_html_to_text((char*) e-event.msg.message, NULL, NULL, packet + sizeof(struct gg_recv_msg80)); + free(e-event.msg.formats); + e-event.msg.formats_length = fmt_len; + e-event.msg.formats = malloc(fmt_len); + + if (e-event.msg.formats == NULL) { + gg_debug_session(sess, GG_DEBUG_MISC, // gg_session_handle_recv_msg_80() out of memory\n); + goto fail; + } + + gg_message_html_to_text((char*) e-event.msg.message, e-event.msg.formats, NULL, packet + sizeof(struct gg_recv_msg80)); } else { e-event.msg.message = (unsigned char*) gg_encoding_convert(packet + offset_plain, GG_ENCODING_CP1250, sess-encoding, -1, -1); diff --git a/test/automatic/script/20-messages.scr b/test/automatic/script/20-messages.scr index c659b33..acaf7ec 100644 --- a/test/automatic/script/20-messages.scr +++ b/test/automatic/script/20-messages.scr @@ -59,8 +59,10 @@ expect event GG_EVENT_MSG ( msg.recipients_count == 0 msg.recipients == NULL - msg.formats_length == 0 - msg.formats == NULL + msg.formats_length == 3 + msg.formats[0] == (char) 0x00 + msg.formats[1] == (char) 0x00 + msg.formats[2] == (char) 0x01 ) expect data (46 00 00 00, auto, 22 22 22 22) @@ -82,11 +84,10 @@ expect event GG_EVENT_MSG ( msg.recipients_count == 0 msg.recipients == NULL - msg.formats_length == 4 - msg.formats[0] == (char) 0x12 - msg.formats[1] == (char) 0x34 - msg.formats[2] == (char) 0x56 - msg.formats[3] == (char) 0x78 + msg.formats_length == 3 + msg.formats[0] == (char) 0x00 + msg.formats[1] == (char) 0x00 + msg.formats[2] == (char) 0x01 ) expect data (46 00 00 00, auto, 22 22 00 22) @@ -110,8 +111,10 @@ expect event GG_EVENT_MSG ( msg.recipients[1] == (int) 2 msg.recipients[2] == (int) 3 - msg.formats_length == 0 - msg.formats == NULL + msg.formats_length == 3 + msg.formats[0] == (char) 0x00 + msg.formats[1] == (char) 0x00 + msg.formats[2] == (char) 0x01 ) expect data (46 00 00 00, auto, xx xx xx xx) @@ -169,11 +172,10 @@ expect event GG_EVENT_MSG ( msg.recipients[1] == (int) 2 msg.recipients[2] == (int) 3 - msg.formats_length == 4 - msg.formats[0] == (char) 0x12 - msg.formats[1] == (char) 0x34 - msg.formats[2] == (char) 0x56 - msg.formats[3] == (char) 0x78 + msg.formats_length == 3 + msg.formats[0] == (char) 0x00 + msg.formats[1] == (char) 0x00 + msg.formats[2] == (char) 0x01 ) expect data (46 00 00 00, auto, xx xx xx xx) -- 1.7.6.1 ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
[libgadu-devel] [PATCH 14/14] Więcej automatycznych testów dla funkcji gg_message_html_to_text()
--- test/automatic/message2.c | 129 ++-- 1 files changed, 111 insertions(+), 18 deletions(-) diff --git a/test/automatic/message2.c b/test/automatic/message2.c index e01f5fd..8add069 100644 --- a/test/automatic/message2.c +++ b/test/automatic/message2.c @@ -127,31 +127,79 @@ const struct test_data text_to_html[] = const struct test_data html_to_text[] = { /* Typowa wiadomość */ - { SPAN(lt;bzduragt;brquot;alaamp;maapos;kotaquot;), bzdura\n\alama'kota\ }, + { SPAN(lt;bzduragt;brquot;alaamp;maapos;kotaquot;), bzdura\n\alama'kota\, GG_ENCODING_UTF8, \x00\x00\x08\x00\x00\x00, 6 }, /* Niepoprawny tag */ - { test, }, + { test, , GG_ENCODING_UTF8 }, /* Tagi do wycięcia */ - { foobar/baz, bar }, + { foobar/baz, bar, GG_ENCODING_UTF8 }, /* Poprawne encje */ - { lt;amp;quot;apos;nbsp;gt;, \'\xc2\xa0 }, + { lt;amp;quot;apos;nbsp;gt;, \'\xc2\xa0, GG_ENCODING_UTF8 }, /* Niepoprawne encje */ - { testtest;test#123;test#xabc;test, test?test?test?test }, + { testtest;test#123;test#xabc;test, test?test?test?test, GG_ENCODING_UTF8 }, /* Różne warianty br */ - { abrbbr/cbr /d, a\nb\nc\nd }, + { abrbbr/cbr /d, a\nb\nc\nd, GG_ENCODING_UTF8 }, /* Niepoprawne tagi */ - { foobar;bazfoo\barfoobar, }, + { foobar;bazfoo\barfoobar, , GG_ENCODING_UTF8 }, /* Niedokończona encja */ - { http://test/foo?ala=1ma=2kota=3;, http://test/foo?ala=1ma=2kota=3; }, + { http://test/foo?ala=1ma=2kota=3;, http://test/foo?ala=1ma=2kota=3;, GG_ENCODING_UTF8 }, + + /* Obrazek na początku tekstu, przed span */ + { img name=\8877665544332211\ SPAN(test), \xc2\xa0test, GG_ENCODING_UTF8, \x01\x00\x08\x00\x00\x00\x00\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 19 }, + + /* Obrazek na początku tekstu, wewnątrz span */ + { SPAN(img name=\8877665544332211\test), \xc2\xa0test, GG_ENCODING_UTF8, \x01\x00\x08\x00\x00\x00\x00\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 19 }, + + /* Obrazek na końcu tekstu */ + { SPAN(testimg name=\8877665544332211\), test\xc2\xa0, GG_ENCODING_UTF8, \x00\x00\x08\x00\x00\x00\x04\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 19 }, + + /* Obrazek w środku tekstu, tekst na końcu formatowany */ + { SPAN(testimg name=\8877665544332211\test bfoo/b), test\xc2\xa0test foo, GG_ENCODING_UTF8, \x00\x00\x08\x00\x00\x00\x05\x00\x08\x00\x00\x00\x0a\x00\x09\x00\x00\x00\x04\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 31 }, + + /* Bez tekstu, tylko obrazek */ + { img name=\8877665544332211\, \xc2\xa0, GG_ENCODING_UTF8, \x00\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 13 }, + + /* Bez tekstu, dwa obrazki */ + { img name=\8877665544332211\img name=\1122334455667788\, \xc2\xa0\xc2\xa0, GG_ENCODING_UTF8, \x00\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88\x01\x00\x80\x09\x01\x88\x77\x66\x55\x44\x33\x22\x11, 26 }, + + /* Atrybuty na początku, w środku i na końcu tekstu */ + { SPAN(bfoo/bibar/iubaz/u), foobarbaz, GG_ENCODING_UTF8, \x00\x00\x09\x00\x00\x00\x03\x00\x0a\x00\x00\x00\x06\x00\x0c\x00\x00\x00, 18 }, + + /* Mieszane atrybuty */ + { SPAN(bifoo/i/bbubar/u/biubaz/u/i), foobarbaz, GG_ENCODING_UTF8, \x00\x00\x0b\x00\x00\x00\x03\x00\x0d\x00\x00\x00\x06\x00\x0e\x00\x00\x00, 18 }, + + /* Mieszane atrybuty, udziwnione i nie do końca poprawne */ + { SPAN(/ibifoo/ibbubar/u/b/b/biubaz/u/i), foobarbaz, GG_ENCODING_UTF8, \x00\x00\x0b\x00\x00\x00\x03\x00\x0d\x00\x00\x00\x06\x00\x0e\x00\x00\x00, 18 }, + + /* Wszystkie atrybuty */ + { SPAN(biutest/u/i/b), test, GG_ENCODING_UTF8, \x00\x00\x0f\x00\x00\x00, 6 }, + + /* Kolorowy tekst */ + { SPAN_COLOR(123456, test), test, GG_ENCODING_UTF8, \x00\x00\x08\x12\x34\x56, 6 }, + + /* Kolorowy tekst na początku */ + { SPAN_COLOR(123456, foo) SPAN(barbaz), foobarbaz, GG_ENCODING_UTF8, \x00\x00\x08\x12\x34\x56\x03\x00\x08\x00\x00\x00, 12 }, + + /* Kolorowy tekst w środku */ + { SPAN(foo) SPAN_COLOR(123456, bar) SPAN(baz), foobarbaz, GG_ENCODING_UTF8, \x00\x00\x08\x00\x00\x00\x03\x00\x08\x12\x34\x56\x06\x00\x08\x00\x00\x00, 18 }, + + /* Kolorowy tekst na końcu */ + { SPAN(foobar) SPAN_COLOR(123456, baz), foobarbaz, GG_ENCODING_UTF8, \x00\x00\x08\x00\x00\x00\x06\x00\x08\x12\x34\x56, 12 }, + + /* Atrybut w środku znaku unikodowego */ + { SPAN(bż/biółć/i), żółć, GG_ENCODING_UTF8, \x00\x00\x09\x00\x00\x00\x01\x00\x0a\x00\x00\x00, 12 }, + + /* Błąd zgłoszony na ekg-users 5b601e1c.7feabed5.4bfaf8b6.14...@o2.pl, tym razem z drugiej strony */ + { SPAN(testbbolda/btest), testboldatest, GG_ENCODING_UTF8, \x00\x00\x08\x00\x00\x00\x04\x00\x09\x00\x00\x00\x09\x00\x08\x00\x00\x00, 18 }, /* Pusty tekst */ - { , }, + { , , GG_ENCODING_UTF8 }, };
[PATCH v2 00/13] Zmiany w obsłudze formatowanych wiadomości
Przesyłam serię ponownie. Jedyna zmiana to wycofanie z serii poprzedniego patcha 08, bo okazał się zupełnie niepotrzeby, oraz dostosowanie dalszych łatek, aby się poprawnie nakładały. Pozdrawiam Bartosz Brachaczek (13): Usunięcie niepotrzebnej zmiennej Bardziej zwracamy uwagę na niepowodzenia w alokacji pamięci Pozwalamy przekazać tekst w CP1250 do funkcji gg_message_text_to_html Dla wiadomości przychodzących zawsze ustawiamy pole xhtml_message Poprawne sprawdzanie, czy bajt jest kontynuacją znaku w UTF-8 Dla każdego znaku sprawdzamy wszystkie atrybuty formatowania Mała zmiana w radzeniu sobie z domyślnym kolorem wiadomości Znaki oznaczone jako GG_FONT_IMAGE nie są częścią wiadomości Nie otwieramy niepotrzebnie na nowo taga span Zmiana typu argumentu attr gg_message_text_to_html() na const unsigned char* oraz usunięcie zbędnej zmiennej Rozbudowanie funkcji gg_message_html_to_text() o możliwość generowania atrybutów formatowania Jeśli podmieniamy message, zapewniajmy również własną wersję formats Więcej automatycznych testów dla funkcji gg_message_html_to_text() include/message.h |4 +- src/encoding.c|5 +- src/handlers.c| 73 +- src/libgadu.c |4 +- src/message.c | 393 ++--- test/automatic/message2.c | 226 +++ test/automatic/script/20-messages.scr | 32 ++-- 7 files changed, 571 insertions(+), 166 deletions(-) -- 1.7.6.1 ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
[libgadu-devel] [PATCH v2 03/13] Pozwalamy przekazać tekst w CP1250 do funkcji gg_message_text_to_html
--- include/message.h |2 +- src/libgadu.c |4 ++-- src/message.c | 11 ++- test/automatic/message2.c |4 ++-- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/include/message.h b/include/message.h index 824f1a8..9d02baf 100644 --- a/include/message.h +++ b/include/message.h @@ -51,6 +51,6 @@ int gg_message_init(gg_message_t *gm, int msgclass, int seq, uin_t *recipients, #endif size_t gg_message_html_to_text(char *dst, const char *html); -size_t gg_message_text_to_html(char *dst, const char *utf_msg, const char *format, size_t format_len); +size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encoding, const char *format, size_t format_len); #endif /* LIBGADU_MESSAGE_H */ diff --git a/src/libgadu.c b/src/libgadu.c index aec389c..7084267 100644 --- a/src/libgadu.c +++ b/src/libgadu.c @@ -1457,7 +1457,7 @@ int gg_send_message_confer_richtext(struct gg_session *sess, int msgclass, int r formatlen = 9; } - len = gg_message_text_to_html(NULL, utf_msg, (const char*) format + 3, formatlen - 3); + len = gg_message_text_to_html(NULL, utf_msg, GG_ENCODING_UTF8, (const char*) format + 3, formatlen - 3); html_msg = malloc(len + 1); @@ -1466,7 +1466,7 @@ int gg_send_message_confer_richtext(struct gg_session *sess, int msgclass, int r goto cleanup; } - gg_message_text_to_html(html_msg, utf_msg, (const char*) format + 3, formatlen - 3); + gg_message_text_to_html(html_msg, utf_msg, GG_ENCODING_UTF8, (const char*) format + 3, formatlen - 3); s80.seq = gg_fix32(seq_no); s80.msgclass = gg_fix32(msgclass); diff --git a/src/message.c b/src/message.c index 222fe65..d06da5f 100644 --- a/src/message.c +++ b/src/message.c @@ -292,14 +292,14 @@ const char *gg_message_get_html(gg_message_t *gm) free(gm-html_converted); - len = gg_message_text_to_html(NULL, gm-text, gm-attributes, gm-attributes_length); + len = gg_message_text_to_html(NULL, gm-text, GG_ENCODING_UTF8, gm-attributes, gm-attributes_length); gm-html_converted = malloc(len + 1); if (gm-html_converted == NULL) return NULL; - gg_message_text_to_html(gm-html_converted, gm-text, gm-attributes, gm-attributes_length); + gg_message_text_to_html(gm-html_converted, gm-text, GG_ENCODING_UTF8, gm-attributes, gm-attributes_length); return gm-html_converted; } @@ -373,7 +373,8 @@ static void gg_append(char *dst, size_t *pos, const void *src, int len) * \internal Zamienia tekst z formatowaniem Gadu-Gadu na HTML. * * \param dst Bufor wynikowy (może być \c NULL) - * \param src Tekst źródłowy w UTF-8 + * \param src Tekst źródłowy + * \param encoding Kodowanie tekstu źródłowego oraz wynikowego * \param format Atrybuty tekstu źródłowego * \param format_len Długość bloku atrybutów tekstu źródłowego * @@ -384,7 +385,7 @@ static void gg_append(char *dst, size_t *pos, const void *src, int len) * * \return Długość tekstu wynikowego bez \c \\0 (nawet jeśli \c dst to \c NULL). */ -size_t gg_message_text_to_html(char *dst, const char *src, const char *format, size_t format_len) +size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encoding, const char *format, size_t format_len) { const char span_fmt[] = span style=\color:#%02x%02x%02x; font-family:'MS Shell Dlg 2'; font-size:9pt; \; const size_t span_len = 75; @@ -530,7 +531,7 @@ size_t gg_message_text_to_html(char *dst, const char *src, const char *format, s /* Sprawdź, czy bajt nie jest kontynuacją znaku unikodowego. */ - if ((src[i] 0xc0) != 0xc0) + if (encoding != GG_ENCODING_UTF8 || (src[i] 0xc0) != 0xc0) char_pos++; if (src[i] == 0) diff --git a/test/automatic/message2.c b/test/automatic/message2.c index 722972b..53b2ce1 100644 --- a/test/automatic/message2.c +++ b/test/automatic/message2.c @@ -138,7 +138,7 @@ static void test_text_to_html(const char *input, const char *attr, size_t attr_l xmlDocPtr doc; #endif - len = gg_message_text_to_html(NULL, input, attr, attr_len); + len = gg_message_text_to_html(NULL, input, GG_ENCODING_UTF8, attr, attr_len); result = malloc(len + 1); @@ -147,7 +147,7 @@ static void test_text_to_html(const char *input, const char *attr, size_t attr_l exit(1); } - gg_message_text_to_html(result, input, attr, attr_len); + gg_message_text_to_html(result, input, GG_ENCODING_UTF8, attr, attr_len); printf(text: \%s\, input); if (attr != NULL) { -- 1.7.6.1 ___ libgadu-devel
[libgadu-devel] [PATCH v2 04/13] Dla wiadomości przychodzących zawsze ustawiamy pole xhtml_message
W razie potrzeby konwertujemy przychodzącą wiadomość w czystym tekście do HTML-a. --- src/handlers.c | 31 --- 1 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/handlers.c b/src/handlers.c index 9100e1b..764c5a0 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -790,6 +790,7 @@ static int gg_session_handle_recv_msg(struct gg_session *sess, uint32_t type, co const struct gg_recv_msg *r = (const struct gg_recv_msg*) packet; const char *payload = packet + sizeof(struct gg_recv_msg); const char *payload_end = packet + length; + size_t len; gg_debug_session(sess, GG_DEBUG_FUNCTION, ** gg_handle_recv_msg(%p, %d, %p);\n, packet, length, e); @@ -828,6 +829,7 @@ static int gg_session_handle_recv_msg(struct gg_session *sess, uint32_t type, co } e-type = GG_EVENT_MSG; + memset(e-event, 0, sizeof(e-event)); e-event.msg.msgclass = gg_fix32(r-msgclass); e-event.msg.sender = gg_fix32(r-sender); e-event.msg.time = gg_fix32(r-time); @@ -839,11 +841,22 @@ static int gg_session_handle_recv_msg(struct gg_session *sess, uint32_t type, co goto fail; } + len = gg_message_text_to_html(NULL, (char*) e-event.msg.message, sess-encoding, e-event.msg.formats, e-event.msg.formats_length); + e-event.msg.xhtml_message = malloc(len + 1); + + if (e-event.msg.xhtml_message == NULL) { + gg_debug_session(sess, GG_DEBUG_MISC, // gg_session_handle_recv_msg() out of memory\n); + goto fail; + } + + gg_message_text_to_html(e-event.msg.xhtml_message, (char*) e-event.msg.message, sess-encoding, e-event.msg.formats, e-event.msg.formats_length); + gg_session_send_msg_ack(sess, gg_fix32(r-seq)); return 0; fail: free(e-event.msg.message); + free(e-event.msg.xhtml_message); free(e-event.msg.recipients); free(e-event.msg.formats); return -1; @@ -904,6 +917,7 @@ static int gg_session_handle_recv_msg_80(struct gg_session *sess, uint32_t type, } e-type = (type != GG_RECV_OWN_MSG) ? GG_EVENT_MSG : GG_EVENT_MULTILOGON_MSG; + memset(e-event, 0, sizeof(e-event)); e-event.msg.msgclass = gg_fix32(r-msgclass); e-event.msg.sender = gg_fix32(r-sender); e-event.msg.time = gg_fix32(r-time); @@ -932,7 +946,7 @@ static int gg_session_handle_recv_msg_80(struct gg_session *sess, uint32_t type, } } else { if (offset_plain sizeof(struct gg_recv_msg80)) { - int len; + size_t len; len = gg_message_html_to_text(NULL, packet + sizeof(struct gg_recv_msg80)); e-event.msg.message = malloc(len + 1); @@ -960,8 +974,19 @@ static int gg_session_handle_recv_msg_80(struct gg_session *sess, uint32_t type, gg_debug_session(sess, GG_DEBUG_MISC, // gg_session_handle_recv_msg_80() out of memory\n); goto fail; } - } else - e-event.msg.xhtml_message = NULL; + } else { + size_t len; + + len = gg_message_text_to_html(NULL, (char*) e-event.msg.message, sess-encoding, e-event.msg.formats, e-event.msg.formats_length); + e-event.msg.xhtml_message = malloc(len + 1); + + if (e-event.msg.xhtml_message == NULL) { + gg_debug_session(sess, GG_DEBUG_MISC, // gg_session_handle_recv_msg_80() out of memory\n); + goto fail; + } + + gg_message_text_to_html(e-event.msg.xhtml_message, (char*) e-event.msg.message, sess-encoding, e-event.msg.formats, e-event.msg.formats_length); + } gg_session_send_msg_ack(sess, gg_fix32(r-seq)); return 0; -- 1.7.6.1 ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
[libgadu-devel] [PATCH v2 05/13] Poprawne sprawdzanie, czy bajt jest kontynuacją znaku w UTF-8
--- src/encoding.c |5 + src/message.c | 18 +- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/encoding.c b/src/encoding.c index ef2ff5c..41822df 100644 --- a/src/encoding.c +++ b/src/encoding.c @@ -136,11 +136,8 @@ static char *gg_encoding_convert_utf8_cp1250(const char *src, int src_length, in uint32_t uc = 0, uc_min = 0; for (i = 0, len = 0; (src[i] != 0) (i src_length); i++) { - if ((src[i] 0xc0) == 0xc0) { + if ((src[i] 0xc0) != 0x80) len++; - } else if ((src[i] 0x80) == 0x00) { - len++; - } } if ((dst_length != -1) (len dst_length)) diff --git a/src/message.c b/src/message.c index d06da5f..d849750 100644 --- a/src/message.c +++ b/src/message.c @@ -415,11 +415,21 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin * na końcu tekstu. */ for (i = 0; ; i++) { + int in_char = 0; + + /* Sprawdź, czy bajt jest kontynuacją znaku UTF-8. */ + if (encoding == GG_ENCODING_UTF8 (src[i] 0xc0) == 0x80) + in_char = 1; + /* Analizuj atrybuty tak długo jak dotyczą aktualnego znaku. */ for (;;) { unsigned char attr; size_t attr_pos; + /* Nie wstawiamy niczego wewnątrz wielobajtowego znaku UTF-8. */ + if (in_char) + break; + if (format_idx + 3 format_len) break; @@ -529,13 +539,11 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin len++; } - /* Sprawdź, czy bajt nie jest kontynuacją znaku unikodowego. */ - - if (encoding != GG_ENCODING_UTF8 || (src[i] 0xc0) != 0xc0) - char_pos++; - if (src[i] == 0) break; + + if (!in_char) + char_pos++; } /* Zamknij tagi. */ -- 1.7.6.1 ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
[libgadu-devel] [PATCH v2 06/13] Dla każdego znaku sprawdzamy wszystkie atrybuty formatowania
Ostatni z dodanych testów pokazuje dlaczego ta zmiana była konieczna. Krótko mówiąc, oryginalny klient wcale nie gwarantuje, że prześle atrybuty formatowania posortowane niemalejąco według pozycji w tekście, jak do tej pory zakładaliśmy. --- src/message.c | 79 +++-- test/automatic/message2.c |8 - 2 files changed, 47 insertions(+), 40 deletions(-) diff --git a/src/message.c b/src/message.c index d849750..125cc72 100644 --- a/src/message.c +++ b/src/message.c @@ -392,36 +392,25 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin const char img_fmt[] = img name=\%02x%02x%02x%02x%02x%02x%02x%02x\; const size_t img_len = 29; size_t char_pos = 0; - size_t format_idx = 0; unsigned char old_attr = 0; const unsigned char *color = (const unsigned char*) \x00\x00\x00; + int in_span = 0; unsigned int i; - size_t len; + size_t len = 0; const unsigned char *format_ = (const unsigned char*) format; - len = 0; - - /* Nie mamy atrybutów dla pierwsze znaku, a tekst nie jest pusty, więc -* tak czy inaczej trzeba otworzyć span. */ - - if (src[0] != 0 (format_idx + 3 format_len || (format_[format_idx] | (format_[format_idx + 1] 8)) != 0)) { - if (dst != NULL) - sprintf(dst[len], span_fmt, 0, 0, 0); - - len += span_len; - } - /* Pętla przechodzi też przez kończące \0, żeby móc dokleić obrazek * na końcu tekstu. */ for (i = 0; ; i++) { int in_char = 0; + size_t format_idx = 0; /* Sprawdź, czy bajt jest kontynuacją znaku UTF-8. */ if (encoding == GG_ENCODING_UTF8 (src[i] 0xc0) == 0x80) in_char = 1; - /* Analizuj atrybuty tak długo jak dotyczą aktualnego znaku. */ + /* Analizuj wszystkie atrybuty dotyczące aktualnego znaku. */ for (;;) { unsigned char attr; size_t attr_pos; @@ -434,10 +423,6 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin break; attr_pos = format_[format_idx] | (format_[format_idx + 1] 8); - - if (attr_pos != char_pos) - break; - attr = format_[format_idx + 2]; /* Nie doklejaj atrybutów na końcu, co najwyżej obrazki. */ @@ -447,19 +432,28 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin format_idx += 3; - if ((attr (GG_FONT_BOLD | GG_FONT_ITALIC | GG_FONT_UNDERLINE | GG_FONT_COLOR)) != 0 || (attr == 0 old_attr != 0)) { - if (char_pos != 0) { - if ((old_attr GG_FONT_UNDERLINE) != 0) - gg_append(dst, len, /u, 4); + if (attr_pos != char_pos) { + if ((attr GG_FONT_COLOR) != 0) + format_idx += 3; + if ((attr GG_FONT_IMAGE) != 0) + format_idx += 10; + + continue; + } - if ((old_attr GG_FONT_ITALIC) != 0) - gg_append(dst, len, /i, 4); + if ((old_attr GG_FONT_UNDERLINE) != 0) + gg_append(dst, len, /u, 4); - if ((old_attr GG_FONT_BOLD) != 0) - gg_append(dst, len, /b, 4); + if ((old_attr GG_FONT_ITALIC) != 0) + gg_append(dst, len, /i, 4); - if (src[i] != 0) - gg_append(dst, len, /span, 7); + if ((old_attr GG_FONT_BOLD) != 0) + gg_append(dst, len, /b, 4); + + if ((attr (GG_FONT_BOLD | GG_FONT_ITALIC | GG_FONT_UNDERLINE | GG_FONT_COLOR)) != 0 || (attr == 0 old_attr != 0)) { + if (in_span) { + gg_append(dst, len, /span, 7); + in_span = 0; } if (((attr GG_FONT_COLOR) != 0) (format_idx + 3 = format_len)) { @@ -472,12 +466,10 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin if (src[i] != 0) { if (dst != NULL)
[libgadu-devel] [PATCH v2 09/13] Nie otwieramy niepotrzebnie na nowo taga span
--- src/message.c | 27 --- test/automatic/message2.c | 14 +++--- test/automatic/script/20-messages.scr |2 +- 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/message.c b/src/message.c index 7c35cb1..ab43bbd 100644 --- a/src/message.c +++ b/src/message.c @@ -394,6 +394,7 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin size_t char_pos = 0; unsigned char old_attr = 0; const unsigned char default_color[] = {'\x00', '\x00', '\x00'}; + const unsigned char *old_color = NULL; int in_span = 0; unsigned int i; size_t len = 0; @@ -455,14 +456,9 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin if ((old_attr GG_FONT_BOLD) != 0) gg_append(dst, len, /b, 4); - if ((attr (GG_FONT_BOLD | GG_FONT_ITALIC | GG_FONT_UNDERLINE | GG_FONT_COLOR)) != 0 || (attr == 0 old_attr != 0)) { + if ((attr (GG_FONT_BOLD | GG_FONT_ITALIC | GG_FONT_UNDERLINE | GG_FONT_COLOR)) != 0) { const unsigned char *color; - if (in_span) { - gg_append(dst, len, /span, 7); - in_span = 0; - } - if (((attr GG_FONT_COLOR) != 0) (format_idx + 3 = format_len)) { color = format_[format_idx]; format_idx += 3; @@ -470,12 +466,20 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin color = default_color; } - if (src[i] != 0) { - if (dst != NULL) - sprintf(dst[len], span_fmt, color[0], color[1], color[2]); + if (old_color == NULL || memcmp(color, old_color, 3) != 0) { + if (in_span) { + gg_append(dst, len, /span, 7); + in_span = 0; + } + + if (src[i] != 0) { + if (dst != NULL) + sprintf(dst[len], span_fmt, color[0], color[1], color[2]); - len += span_len; - in_span = 1; + len += span_len; + in_span = 1; + old_color = color; + } } } @@ -529,6 +533,7 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin len += span_len; in_span = 1; + old_color = default_color; } /* Doklej znak zachowując htmlowe escapowanie. */ diff --git a/test/automatic/message2.c b/test/automatic/message2.c index 5c34c40..6d92c7f 100644 --- a/test/automatic/message2.c +++ b/test/automatic/message2.c @@ -41,10 +41,10 @@ const struct test_data text_to_html[] = { test test, SPAN(testimg name=\8877665544332211\test), GG_ENCODING_UTF8, \x04\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 13 }, /* Obrazek w środku tekstu, tekst na końcu formatowany */ - { test test foo, SPAN(testimg name=\8877665544332211\test ) SPAN(bfoo/b), GG_ENCODING_UTF8, \x04\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88\x0a\x00\x01, 16 }, + { test test foo, SPAN(testimg name=\8877665544332211\test bfoo/b), GG_ENCODING_UTF8, \x04\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88\x0a\x00\x01, 16 }, /* Obrazek w środku tekstu, tekst na końcu formatowany, dokładnie tak jak wysyła oryginalny klient */ - { test\xa0test foo, SPAN(testimg name=\8877665544332211\) SPAN(test ) SPAN(bfoo/b), GG_ENCODING_CP1250, \x00\x00\x08\x00\x00\x00\x05\x00\x08\x00\x00\x00\x0a\x00\x09\x00\x00\x00\x04\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 31 }, + { test\xa0test foo, SPAN(testimg name=\8877665544332211\test bfoo/b), GG_ENCODING_CP1250, \x00\x00\x08\x00\x00\x00\x05\x00\x08\x00\x00\x00\x0a\x00\x09\x00\x00\x00\x04\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 31 }, /* Obrazek poza tekstem */ { test, SPAN(test), GG_ENCODING_UTF8, \x05\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 13 }, @@ -68,10 +68,10 @@ const struct test_data text_to_html[] = { , img
[libgadu-devel] [PATCH v2 08/13] Znaki oznaczone jako GG_FONT_IMAGE nie są częścią wiadomości
--- src/message.c | 14 ++ test/automatic/message2.c | 99 + 2 files changed, 78 insertions(+), 35 deletions(-) diff --git a/src/message.c b/src/message.c index 7fc2145..7c35cb1 100644 --- a/src/message.c +++ b/src/message.c @@ -410,6 +410,11 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin if (encoding == GG_ENCODING_UTF8 (src[i] 0xc0) == 0x80) in_char = 1; + /* GG_FONT_IMAGE powinno dotyczyć tylko jednego znaku, więc czyścimy stary atrybut */ + + if (!in_char (old_attr GG_FONT_IMAGE) != 0) + old_attr = ~GG_FONT_IMAGE; + /* Analizuj wszystkie atrybuty dotyczące aktualnego znaku. */ for (;;) { unsigned char attr; @@ -506,6 +511,15 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin if (src[i] == 0) break; + /* Znaki oznaczone jako GG_FONT_IMAGE nie są częścią wiadomości. */ + + if ((old_attr GG_FONT_IMAGE) != 0) { + if (!in_char) + char_pos++; + + continue; + } + /* Jesteśmy na początku tekstu i choć nie było atrybutów dla pierwszego * znaku, ponieważ tekst nie jest pusty, trzeba otworzyć span. */ diff --git a/test/automatic/message2.c b/test/automatic/message2.c index 77505ca..5c34c40 100644 --- a/test/automatic/message2.c +++ b/test/automatic/message2.c @@ -1,5 +1,6 @@ #include stdio.h #include string.h +#include libgadu.h #include message.h #include config.h #ifdef HAVE_LIBXML2 @@ -11,6 +12,7 @@ struct test_data { const char *src; const char *dst; + gg_encoding_t encoding; const char *attr; size_t attr_len; }; @@ -21,82 +23,100 @@ struct test_data const struct test_data text_to_html[] = { /* Typowa wiadomość */ - { bzdura\n\alama'kota\, SPAN(lt;bzduragt;brquot;alaamp;maapos;kotaquot;) }, + { bzdura\n\alama'kota\, SPAN(lt;bzduragt;brquot;alaamp;maapos;kotaquot;), GG_ENCODING_UTF8 }, /* Obrazek na początku tekstu */ - { test, img name=\8877665544332211\ SPAN(test), \x00\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 13 }, + { test, img name=\8877665544332211\ SPAN(test), GG_ENCODING_UTF8, \x00\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 13 }, + + /* Obrazek na początku tekstu, dokładnie tak jak wysyła oryginalny klient */ + { \xa0test, img name=\8877665544332211\ SPAN(test), GG_ENCODING_CP1250, \x01\x00\x08\x00\x00\x00\x00\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 19 }, /* Obrazek na końcu tekstu */ - { test, SPAN(testimg name=\8877665544332211\), \x04\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 13 }, + { test, SPAN(testimg name=\8877665544332211\), GG_ENCODING_UTF8, \x04\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 13 }, + + /* Obrazek na końcu tekstu, dokładnie tak jak wysyła oryginalny klient */ + { test\xa0, SPAN(testimg name=\8877665544332211\), GG_ENCODING_CP1250, \x00\x00\x08\x00\x00\x00\x04\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 19 }, /* Obrazek w środku tekstu */ - { testtest, SPAN(testimg name=\8877665544332211\test), \x04\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 13 }, + { test test, SPAN(testimg name=\8877665544332211\test), GG_ENCODING_UTF8, \x04\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 13 }, - /* Obrazek w środku tekstu, tekst na końcu formatowany, atrybuty w zwykłej kolejności */ - { testtest foo, SPAN(testimg name=\8877665544332211\test ) SPAN(bfoo/b), \x04\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88\x09\x00\x01, 16 }, + /* Obrazek w środku tekstu, tekst na końcu formatowany */ + { test test foo, SPAN(testimg name=\8877665544332211\test ) SPAN(bfoo/b), GG_ENCODING_UTF8, \x04\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88\x0a\x00\x01, 16 }, - /* Obrazek w środku tekstu, tekst na końcu formatowany, atrybuty obrazka na końcu, czyli tak jak wysyła oryginalny klient */ - { testtest foo, SPAN(testimg name=\8877665544332211\test ) SPAN(bfoo/b), \x09\x00\x01\x04\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 16 }, + /* Obrazek w środku tekstu, tekst na końcu formatowany, dokładnie tak jak wysyła oryginalny klient */ + { test\xa0test foo, SPAN(testimg name=\8877665544332211\) SPAN(test ) SPAN(bfoo/b), GG_ENCODING_CP1250, \x00\x00\x08\x00\x00\x00\x05\x00\x08\x00\x00\x00\x0a\x00\x09\x00\x00\x00\x04\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 31 }, /* Obrazek poza tekstem */ - { test, SPAN(test), \x05\x00\x80\x09\x01\x11\x22\x33\x44\x55\x66\x77\x88, 13 }, + { test, SPAN(test), GG_ENCODING_UTF8,
[libgadu-devel] [PATCH v2 11/13] Rozbudowanie funkcji gg_message_html_to_text() o możliwość generowania atrybutów formatowania
--- include/message.h |2 +- src/handlers.c|4 +- src/message.c | 237 + test/automatic/message2.c |4 +- 4 files changed, 222 insertions(+), 25 deletions(-) diff --git a/include/message.h b/include/message.h index ced7f9a..be280b7 100644 --- a/include/message.h +++ b/include/message.h @@ -50,7 +50,7 @@ int gg_message_init(gg_message_t *gm, int msgclass, int seq, uin_t *recipients, #endif -size_t gg_message_html_to_text(char *dst, const char *html); +size_t gg_message_html_to_text(char *dst, unsigned char *format, size_t *format_len, const char *html); size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encoding, const unsigned char *format, size_t format_len); #endif /* LIBGADU_MESSAGE_H */ diff --git a/src/handlers.c b/src/handlers.c index 764c5a0..2e53b70 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -948,7 +948,7 @@ static int gg_session_handle_recv_msg_80(struct gg_session *sess, uint32_t type, if (offset_plain sizeof(struct gg_recv_msg80)) { size_t len; - len = gg_message_html_to_text(NULL, packet + sizeof(struct gg_recv_msg80)); + len = gg_message_html_to_text(NULL, NULL, NULL, packet + sizeof(struct gg_recv_msg80)); e-event.msg.message = malloc(len + 1); if (e-event.msg.message == NULL) { @@ -956,7 +956,7 @@ static int gg_session_handle_recv_msg_80(struct gg_session *sess, uint32_t type, goto fail; } - gg_message_html_to_text((char*) e-event.msg.message, packet + sizeof(struct gg_recv_msg80)); + gg_message_html_to_text((char*) e-event.msg.message, NULL, NULL, packet + sizeof(struct gg_recv_msg80)); } else { e-event.msg.message = (unsigned char*) gg_encoding_convert(packet + offset_plain, GG_ENCODING_CP1250, sess-encoding, -1, -1); diff --git a/src/message.c b/src/message.c index 974a008..858b076 100644 --- a/src/message.c +++ b/src/message.c @@ -361,7 +361,7 @@ int gg_message_get_attributes(gg_message_t *gm, const char **attributes, size_t * \param src Dodawany tekst * \param len Długość dodawanego tekstu */ -static void gg_append(char *dst, size_t *pos, const void *src, int len) +static void gg_append(char *dst, size_t *pos, const void *src, size_t len) { if (dst != NULL) memcpy(dst[*pos], src, len); @@ -589,36 +589,99 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin } /** + * \internal Dokleja nowe atrybuty formatowania, jeśli konieczne, oraz inkrementuje pozycję znaku w tekście. + * + * \param pos Wskaźnik na zmienną przechowującą pozycję znaku w tekście + * \param attr_flag Aktualna flaga atrybutu formatowania + * \param old_attr_flag Wskaźnik na poprzednią flagę atrybutu formatowania + * \param color Wskaźnik na tablicę z aktualnym kolorem RGB (jeśli \p attr_flag nie zawiera flagi \c GG_FONT_COLOR, ignorowane) + * \param old_color Wskaźnik na tablicę z poprzednim kolorem RGB + * \param imgs_size Rozmiar atrybutów formatowania obrazków znajdujących się obecnie w tablicy atrybutów formatowania, w bajtach + * \param format Wskaźnik na wskaźnik do tablicy atrybutów formatowania + * \param format_len Wskaźnik na zmienną zawierającą długość tablicy atrybutów formatowania, w bajtach (może być \c NULL) + */ +static void gg_after_append_formatted_char(uint16_t *pos, unsigned char attr_flag, unsigned char *old_attr_flag, const unsigned char *color, unsigned char *old_color, size_t imgs_size, unsigned char **format, size_t *format_len) +{ + const size_t color_size = 3; + int has_color = 0; + + if ((attr_flag GG_FONT_COLOR) != 0) + has_color = 1; + + if (*old_attr_flag != attr_flag || (has_color memcmp(old_color, color, color_size != 0))) { + size_t attr_size = sizeof(*pos) + sizeof(attr_flag) + (has_color ? color_size : 0); + + if (*format != NULL) { + /* Staramy się naśladować oryginalnego klienta i atrybuty obrazków trzymamy na końcu */ + + *format -= imgs_size; + memmove(*format + attr_size, *format, imgs_size); + + memcpy(*format, pos, sizeof(*pos)); + *format += sizeof(*pos); + memcpy(*format, attr_flag, sizeof(attr_flag)); + *format += sizeof(attr_flag); + if (has_color) { + memcpy(*format, color, color_size); + *format += color_size; + } + + *format += imgs_size; + } + + if (format_len != NULL) + *format_len +=
[libgadu-devel] [PATCH v2 10/13] Zmiana typu argumentu attr gg_message_text_to_html() na const unsigned char* oraz usunięcie zbędnej zmiennej
--- include/message.h |2 +- src/libgadu.c |4 ++-- src/message.c | 25 - test/automatic/message2.c |4 ++-- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/include/message.h b/include/message.h index 9d02baf..ced7f9a 100644 --- a/include/message.h +++ b/include/message.h @@ -51,6 +51,6 @@ int gg_message_init(gg_message_t *gm, int msgclass, int seq, uin_t *recipients, #endif size_t gg_message_html_to_text(char *dst, const char *html); -size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encoding, const char *format, size_t format_len); +size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encoding, const unsigned char *format, size_t format_len); #endif /* LIBGADU_MESSAGE_H */ diff --git a/src/libgadu.c b/src/libgadu.c index 7084267..c59f499 100644 --- a/src/libgadu.c +++ b/src/libgadu.c @@ -1457,7 +1457,7 @@ int gg_send_message_confer_richtext(struct gg_session *sess, int msgclass, int r formatlen = 9; } - len = gg_message_text_to_html(NULL, utf_msg, GG_ENCODING_UTF8, (const char*) format + 3, formatlen - 3); + len = gg_message_text_to_html(NULL, utf_msg, GG_ENCODING_UTF8, format + 3, formatlen - 3); html_msg = malloc(len + 1); @@ -1466,7 +1466,7 @@ int gg_send_message_confer_richtext(struct gg_session *sess, int msgclass, int r goto cleanup; } - gg_message_text_to_html(html_msg, utf_msg, GG_ENCODING_UTF8, (const char*) format + 3, formatlen - 3); + gg_message_text_to_html(html_msg, utf_msg, GG_ENCODING_UTF8, format + 3, formatlen - 3); s80.seq = gg_fix32(seq_no); s80.msgclass = gg_fix32(msgclass); diff --git a/src/message.c b/src/message.c index ab43bbd..974a008 100644 --- a/src/message.c +++ b/src/message.c @@ -385,7 +385,7 @@ static void gg_append(char *dst, size_t *pos, const void *src, int len) * * \return Długość tekstu wynikowego bez \c \\0 (nawet jeśli \c dst to \c NULL). */ -size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encoding, const char *format, size_t format_len) +size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encoding, const unsigned char *format, size_t format_len) { const char span_fmt[] = span style=\color:#%02x%02x%02x; font-family:'MS Shell Dlg 2'; font-size:9pt; \; const size_t span_len = 75; @@ -398,7 +398,6 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin int in_span = 0; unsigned int i; size_t len = 0; - const unsigned char *format_ = (const unsigned char*) format; /* Pętla przechodzi też przez kończące \0, żeby móc dokleić obrazek * na końcu tekstu. */ @@ -428,8 +427,8 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin if (format_idx + 3 format_len) break; - attr_pos = format_[format_idx] | (format_[format_idx + 1] 8); - attr = format_[format_idx + 2]; + attr_pos = format[format_idx] | (format[format_idx + 1] 8); + attr = format[format_idx + 2]; /* Nie doklejaj atrybutów na końcu, co najwyżej obrazki. */ @@ -460,7 +459,7 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin const unsigned char *color; if (((attr GG_FONT_COLOR) != 0) (format_idx + 3 = format_len)) { - color = format_[format_idx]; + color = format[format_idx]; format_idx += 3; } else { color = default_color; @@ -495,14 +494,14 @@ size_t gg_message_text_to_html(char *dst, const char *src, gg_encoding_t encodin if (((attr GG_FONT_IMAGE) != 0) (format_idx + 10 = format_len)) { if (dst != NULL) { sprintf(dst[len], img_fmt, - format_[format_idx + 9], - format_[format_idx + 8], - format_[format_idx + 7], - format_[format_idx + 6], - format_[format_idx + 5], - format_[format_idx + 4], - format_[format_idx + 3], - format_[format_idx + 2]); +
[libgadu-devel] [PATCH v2 12/13] Jeśli podmieniamy message, zapewniajmy również własną wersję formats
Dzięki tej zmianie formatowanie w odebranych wiadomościach m.in. od Infobota jest poprawne. --- src/handlers.c| 15 --- test/automatic/script/20-messages.scr | 30 -- 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/src/handlers.c b/src/handlers.c index 2e53b70..962f265 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -946,9 +946,9 @@ static int gg_session_handle_recv_msg_80(struct gg_session *sess, uint32_t type, } } else { if (offset_plain sizeof(struct gg_recv_msg80)) { - size_t len; + size_t len, fmt_len; - len = gg_message_html_to_text(NULL, NULL, NULL, packet + sizeof(struct gg_recv_msg80)); + len = gg_message_html_to_text(NULL, NULL, fmt_len, packet + sizeof(struct gg_recv_msg80)); e-event.msg.message = malloc(len + 1); if (e-event.msg.message == NULL) { @@ -956,7 +956,16 @@ static int gg_session_handle_recv_msg_80(struct gg_session *sess, uint32_t type, goto fail; } - gg_message_html_to_text((char*) e-event.msg.message, NULL, NULL, packet + sizeof(struct gg_recv_msg80)); + free(e-event.msg.formats); + e-event.msg.formats_length = fmt_len; + e-event.msg.formats = malloc(fmt_len); + + if (e-event.msg.formats == NULL) { + gg_debug_session(sess, GG_DEBUG_MISC, // gg_session_handle_recv_msg_80() out of memory\n); + goto fail; + } + + gg_message_html_to_text((char*) e-event.msg.message, e-event.msg.formats, NULL, packet + sizeof(struct gg_recv_msg80)); } else { e-event.msg.message = (unsigned char*) gg_encoding_convert(packet + offset_plain, GG_ENCODING_CP1250, sess-encoding, -1, -1); diff --git a/test/automatic/script/20-messages.scr b/test/automatic/script/20-messages.scr index c659b33..acaf7ec 100644 --- a/test/automatic/script/20-messages.scr +++ b/test/automatic/script/20-messages.scr @@ -59,8 +59,10 @@ expect event GG_EVENT_MSG ( msg.recipients_count == 0 msg.recipients == NULL - msg.formats_length == 0 - msg.formats == NULL + msg.formats_length == 3 + msg.formats[0] == (char) 0x00 + msg.formats[1] == (char) 0x00 + msg.formats[2] == (char) 0x01 ) expect data (46 00 00 00, auto, 22 22 22 22) @@ -82,11 +84,10 @@ expect event GG_EVENT_MSG ( msg.recipients_count == 0 msg.recipients == NULL - msg.formats_length == 4 - msg.formats[0] == (char) 0x12 - msg.formats[1] == (char) 0x34 - msg.formats[2] == (char) 0x56 - msg.formats[3] == (char) 0x78 + msg.formats_length == 3 + msg.formats[0] == (char) 0x00 + msg.formats[1] == (char) 0x00 + msg.formats[2] == (char) 0x01 ) expect data (46 00 00 00, auto, 22 22 00 22) @@ -110,8 +111,10 @@ expect event GG_EVENT_MSG ( msg.recipients[1] == (int) 2 msg.recipients[2] == (int) 3 - msg.formats_length == 0 - msg.formats == NULL + msg.formats_length == 3 + msg.formats[0] == (char) 0x00 + msg.formats[1] == (char) 0x00 + msg.formats[2] == (char) 0x01 ) expect data (46 00 00 00, auto, xx xx xx xx) @@ -169,11 +172,10 @@ expect event GG_EVENT_MSG ( msg.recipients[1] == (int) 2 msg.recipients[2] == (int) 3 - msg.formats_length == 4 - msg.formats[0] == (char) 0x12 - msg.formats[1] == (char) 0x34 - msg.formats[2] == (char) 0x56 - msg.formats[3] == (char) 0x78 + msg.formats_length == 3 + msg.formats[0] == (char) 0x00 + msg.formats[1] == (char) 0x00 + msg.formats[2] == (char) 0x01 ) expect data (46 00 00 00, auto, xx xx xx xx) -- 1.7.6.1 ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
[libgadu-devel] Zrywanie połączenia z serwerem od wersji trunk r1142 wzwyż
Cześć, Zaktualizowałem swoje libgadu do najnowszej wersji z gałęzi trunk (tj. r1146) i mam problemy ze zrywaniem połączenia z serwerem chwilę po jego uzyskaniu. Odrobina testów wykazała, że problemy zaczęły się wraz z wersją r1142. Załączam dwa przykładowe logi z zerwanych sesji. Przed każdym rozłączeniem powtarza się najpierw EAGAIN a potem ERANGE. W razie czego jestem oczywiście gotowy do debugowania ;). Przynajmniej dopóki będę w stanie powtórzyć błąd. Pozdrawiam, Bartosz libgadu-log-1 Description: Binary data libgadu-log-2 Description: Binary data ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
[libgadu-devel] Wiadomości przychodzące i zamiana HTML-a na czysty tekst
Witam, Funkcja gg_session_handle_recv_msg_80() zakłada, że zawsze dostanie wiadomość w czystym tekście, natomiast wiadomość w formacie HTML jest opcjonalna. Jednak, jak widzę, w przypadku dostania wiadomości w formacie HTML wiadomość w czystym tekście jest całkowicie ignorowana i do pola message struktury gg_event_msg jest przypisywany wynik funkcji gg_message_html_to_text() z argumentem zawierającym przesłaną nam wiadomość HTML. I tutaj rodzi się problem, bo jeśli klient libgadu postanowi przeczytać atrybuty formatowania zamiast wiadomości HTML (tak robi Kadu), a wynik funkcji gg_message_html_to_text() będzie się różnił od wiadomości oryginalnie przesłanej przez rozmówcę, to wynikiem będzie błędne wyświetlenie sformatowanej wiadomości. Taka sytuacja ma miejsce w przypadku rozmowy z Infobotem, który w wiadomościach czystym tekstem znaki nowej linii koduje jako \r\n, a nie jako \n, jak oryginalny klient. Trudno mi sobie wyobrazić, jak w rozsądny sposób można by dostosować do takiego przypadku funkcję gg_message_html_to_text(), więc moje pytanie brzmi, dlaczego właściwie libgadu dokonuje konwersji HTML-a do czystego tekstu, zamiast wziąć to, co wysłał rozmówca? Prosta łata, którą załączam, zdaje się rozwiązywać problem i moje testowanie jej w rozmowie z klientem libgadu (Kadu), oryginalnym klientem GG 10.5, botem Infobot oraz botem Allegro nie wykazało żadnych problemów. Pozdrawiam, Bartosz diff --git a/src/handlers.c b/src/handlers.c index a843b4b..17e22f9 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -926,23 +926,7 @@ static int gg_session_handle_recv_msg_80(struct gg_session *sess, uint32_t type, } } - if (sess-encoding == GG_ENCODING_CP1250) { - e-event.msg.message = (unsigned char*) strdup(packet + offset_plain); - } else { - if (offset_plain sizeof(struct gg_recv_msg80)) { - int len; - - len = gg_message_html_to_text(NULL, packet + sizeof(struct gg_recv_msg80)); - e-event.msg.message = malloc(len + 1); - - if (e-event.msg.message == NULL) -goto fail; - - gg_message_html_to_text((char*) e-event.msg.message, packet + sizeof(struct gg_recv_msg80)); - } else { - e-event.msg.message = (unsigned char*) gg_encoding_convert(packet + offset_plain, GG_ENCODING_CP1250, sess-encoding, -1, -1); - } - } + e-event.msg.message = (unsigned char*) gg_encoding_convert(packet + offset_plain, GG_ENCODING_CP1250, sess-encoding, -1, -1); if (offset_plain sizeof(struct gg_recv_msg80)) e-event.msg.xhtml_message = gg_encoding_convert(packet + sizeof(struct gg_recv_msg80), GG_ENCODING_UTF8, sess-encoding, -1, -1); ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
[libgadu-devel] Propozycja zmian w obsłudze przesyłania formatowanych wiadomości HTML
Witam, W Kadu stwierdziliśmy, że miło by było pozbyć się kodu odpowiedzialnego za formatowanie wiadomości GG za pomocą atrybutów i pracować wyłącznie na HTML-u. Stąd propozycja kilku zmian w libgadu. Jestem gotów je zaimplementować, chciałbym tylko się dogadać, jak to ma być zrobione i w czy w ogóle wszystkim to pasuje. Oto propozycje: 1. Stripować nieprzewidzanie przez protokół znaczniki HTML w odebranych wiadomościach (np. script zamieniać na lt;scriptgt;). 2. Jeśli otrzymujemy tylko wiadomość czystym tekstem, konwertować ją do HTML-a. Tutaj widzę, że jest właściwie gotowa funkcja do tego celu. 3. Dodać możliwość wysyłania wiadomości poprzez podanie tylko HTML-a - libgadu zajęło by się przekonwertowaniem go do czystego tekstu z atrybutami formatowania. Pytanie tylko, jak takie funkcje mogłoby się nazywać? Pozdrawiam, Bartosz ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] [PATCH 0/5] Obsługa eksportu i importu listy kontaktów Nowego Gadu-Gadu
W dniu 5 maja 2011 15:11 użytkownik Krzysztof Klinikowski kkszy...@gmail.com napisał: I jakiś mały update samej dokumentacji protokołu związany z tymi pakietami? Mały update dokumentacji protokołu był od początku częścią tej serii łatek i, jak widzę, również został dzisiaj wrzucony. :) Pozdrawiam, Bartosz ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
[libgadu-devel] [PATCH 3/5] Dodanie obsługi pakietu GG_USERLIST100_REQUEST wraz z obsługą kompresji za pomocą zlib (v2)
Sprawdzanie zlib w configure.ac wymaga poprawki. Sam nie mam pojęcia o autotools i zrobiłem to tylko tak, żeby na moim systemie libgadu w ogóle chciało się linkować. Zmiany względem v1: - Kilka deklaracji przesuniętych z libgadu.h do internal.h i protocol.h. --- configure.ac |4 ++ include/internal.h |2 + include/libgadu.h.in | 41 + include/protocol.h | 10 + src/common.c | 95 ++ src/libgadu.c| 64 + src/libgadu.sym |1 + 7 files changed, 217 insertions(+), 0 deletions(-) diff --git a/configure.ac b/configure.ac index ec4d048..e83c1e5 100644 --- a/configure.ac +++ b/configure.ac @@ -194,6 +194,10 @@ if test x$with_pthread = xyes; then AC_DEFINE([GG_CONFIG_PTHREAD_DEFAULT], [], [Defined if pthread resolver is the default one.]) fi +dnl zlib (TODO!) + +LIBS=$LIBS -lz + dnl dnl Sprawdzamy GnuTLS dnl diff --git a/include/internal.h b/include/internal.h index c70326b..dc753e0 100644 --- a/include/internal.h +++ b/include/internal.h @@ -37,6 +37,8 @@ int gg_resolve(int *fd, int *pid, const char *hostname); int gg_resolve_pthread(int *fd, void **resolver, const char *hostname); void gg_resolve_pthread_cleanup(void *resolver, int kill); +unsigned char *gg_deflate(const char *in, size_t *out_lenp); + #ifdef HAVE_UINT64_T uint64_t gg_fix64(uint64_t x); #endif diff --git a/include/libgadu.h.in b/include/libgadu.h.in index fb1d5ef..ee231f4 100644 --- a/include/libgadu.h.in +++ b/include/libgadu.h.in @@ -623,6 +623,7 @@ int gg_send_message_confer_richtext(struct gg_session *sess, int msgclass, int r int gg_send_message_ctcp(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, int message_len); int gg_ping(struct gg_session *sess); int gg_userlist_request(struct gg_session *sess, char type, const char *request); +int gg_userlist100_request(struct gg_session *sess, char type, unsigned int version, char format_type, const char *request); int gg_image_request(struct gg_session *sess, uin_t recipient, int size, uint32_t crc32); int gg_image_reply(struct gg_session *sess, uin_t recipient, const char *filename, const char *image, int size); int gg_typing_notification(struct gg_session *sess, uin_t recipient, int length); @@ -2083,6 +2084,46 @@ struct gg_userlist_reply { uint8_t type; } GG_PACKED; +#ifndef DOXYGEN + +#define GG_USERLIST100_PUT 0x00 +#define GG_USERLIST100_GET 0x02 + +#else + +/** + * \ingroup importexport + * + * Rodzaj zapytania (10.0). + */ +enum { + GG_USERLIST100_PUT, /** Eksport listy kontaktów. */ + GG_USERLIST100_GET, /** Import listy kontaktów. */ +}; + +#endif /* DOXYGEN */ + +#ifndef DOXYGEN + +#define GG_USERLIST100_FORMAT_TYPE_NONE 0x00 +#define GG_USERLIST100_FORMAT_TYPE_GG70 0x01 +#define GG_USERLIST100_FORMAT_TYPE_GG100 0x02 + +#else + +/** + * \ingroup importexport + * + * Typ formatu listy kontaktów (10.0). + */ +enum { + GG_USERLIST100_FORMAT_TYPE_NONE,/** Brak treści listy kontaktów. */ + GG_USERLIST100_FORMAT_TYPE_GG70,/** Format listy kontaktów zgodny z Gadu-Gadu 7.0. */ + GG_USERLIST100_FORMAT_TYPE_GG100, /** Format listy kontaktów zgodny z Gadu-Gadu 10.0. */ +}; + +#endif /* DOXYGEN */ + struct gg_dcc_tiny_packet { uint8_t type; /* rodzaj pakietu */ } GG_PACKED; diff --git a/include/protocol.h b/include/protocol.h index b0b4fde..2c2c06c 100644 --- a/include/protocol.h +++ b/include/protocol.h @@ -299,6 +299,16 @@ struct gg_userlist100_version { uint32_t version; /* numer wersji listy kontaktów */ } GG_PACKED; +#define GG_USERLIST100_REQUEST 0x0040 + +struct gg_userlist100_request { + uint8_t type; /* rodzaj żądania */ + uint32_t version; /* numer ostatniej znanej wersji listy kontaktów bądź 0 */ + uint8_t format_type;/* rodzaj żądanego typu formatu listy kontaktów */ + uint8_t unknown1; /* 0x01 */ + /* char request[]; */ +} GG_PACKED; + #ifdef _WIN32 #pragma pack(pop) #endif diff --git a/src/common.c b/src/common.c index 55e77d9..79fcbb0 100644 --- a/src/common.c +++ b/src/common.c @@ -42,6 +42,9 @@ #include string.h #include unistd.h +#include zlib.h + +#include internal.h #include libgadu.h /** @@ -576,6 +579,98 @@ char *gg_proxy_auth(void) } /** + * \internal Kompresuje dane wejściowe algorytmem Deflate z najwyższym + * stopniem kompresji, tak samo jak oryginalny klient. + * + * Wynik funkcji należy zwolnić za pomocą \c free. + * + * \param in Ciąg znaków do skompresowania, zakończony \c \\0 + * \param out_lenp Wskaźnik na zmienną, do której zostanie zapisana + * długość bufora wynikowego + * + * \return Skompresowany ciąg znaków lub \c NULL w przypadku niepowodzenia. + */ +unsigned char *gg_deflate(const char *in,
[libgadu-devel] [PATCH 4/5] Dodanie obsługi pakietu GG_USERLIST100_REPLY (v2)
Zmiany względem v1: - Przesunięcie jednej deklaracji z libgadu.h do internal.h. - Usunięcie zapomnianego gg_debug_session z funkcji gg_session_handle_userlist_100_reply. --- include/internal.h |1 + include/libgadu.h.in | 33 +++ include/protocol.h | 10 ++ src/common.c | 87 ++ src/debug.c |1 + src/events.c |4 ++ src/handlers.c | 31 ++ 7 files changed, 167 insertions(+), 0 deletions(-) diff --git a/include/internal.h b/include/internal.h index dc753e0..8f0848f 100644 --- a/include/internal.h +++ b/include/internal.h @@ -38,6 +38,7 @@ int gg_resolve_pthread(int *fd, void **resolver, const char *hostname); void gg_resolve_pthread_cleanup(void *resolver, int kill); unsigned char *gg_deflate(const char *in, size_t *out_lenp); +char *gg_inflate(const unsigned char *in, size_t length); #ifdef HAVE_UINT64_T uint64_t gg_fix64(uint64_t x); diff --git a/include/libgadu.h.in b/include/libgadu.h.in index ee231f4..7ba3286 100644 --- a/include/libgadu.h.in +++ b/include/libgadu.h.in @@ -698,6 +698,7 @@ enum gg_event_t { GG_EVENT_MULTILOGON_INFO, /** Informacja o innych sesjach multilogowania */ GG_EVENT_USERLIST100_VERSION, /** Otrzymano numer wersji listy kontaktów na serwerze (10.0) */ + GG_EVENT_USERLIST100_REPLY, /** Wynik importu lub eksportu listy kontaktów (10.0) */ }; #define GG_EVENT_SEARCH50_REPLY GG_EVENT_PUBDIR50_SEARCH_REPLY @@ -995,6 +996,16 @@ struct gg_event_userlist100_version { }; /** + * Opis zdarzenia \c GG_EVENT_USERLIST100_REPLY. + */ +struct gg_event_userlist100_reply { + char type; /** Rodzaj odpowiedzi */ + uint32_t version; /** Aktualna wersja listy kontaktów na serwerze */ + char format_type; /** Typ formatu listy kontaktów (żądany w \c gg_userlist100_request.format_type) */ + char *reply;/** Treść listy kontaktów w przesyłanej wersji i formacie */ +}; + +/** * Unia wszystkich zdarzeń zwracanych przez funkcje \c gg_watch_fd(), * \c gg_dcc_watch_fd() i \c gg_dcc7_watch_fd(). * @@ -1029,6 +1040,7 @@ union gg_event_union { struct gg_event_msg multilogon_msg; /** Inna sesja wysłała wiadomość (\c GG_EVENT_MULTILOGON_MSG) */ struct gg_event_multilogon_info multilogon_info;/** Informacja o innych sesjach multilogowania (\c GG_EVENT_MULTILOGON_INFO) */ struct gg_event_userlist100_version userlist100_version;/** Informacja o numerze wersji listy kontaktów na serwerze (\c GG_EVENT_USERLIST100_VERSION) */ + struct gg_event_userlist100_reply userlist100_reply;/** Odpowiedź listy kontaktów (10.0) (\c GG_EVENT_USERLIST100_REPLY) */ }; /** @@ -2124,6 +2136,27 @@ enum { #endif /* DOXYGEN */ +#ifndef DOXYGEN + +#define GG_USERLIST100_REPLY_LIST 0x00 +#define GG_USERLIST100_REPLY_ACK 0x10 +#define GG_USERLIST100_REPLY_REJECT 0x12 + +#else + +/** + * \ingroup importexport + * + * Typ odpowiedzi listy kontaktów (10.0). + */ +enum { + GG_USERLIST100_REPLY_LIST, /** W odpowiedzi znajduje się aktualna lista kontaktów na serwerze. */ + GG_USERLIST100_REPLY_ACK, /** Potwierdzenie odebrania nowej wersji listy kontaktów. W polu \c gg_userlist100_reply.version znajduje się numer nowej wersji listy kontaktów. */ + GG_USERLIST100_REPLY_REJECT,/** Odmowa przyjęcia nowej wersji listy kontaktów. W polu \c gg_userlist100_reply.version znajduje się numer wersji listy kontaktów aktualnie przechowywanej przez serwer. */ +}; + +#endif /* DOXYGEN */ + struct gg_dcc_tiny_packet { uint8_t type; /* rodzaj pakietu */ } GG_PACKED; diff --git a/include/protocol.h b/include/protocol.h index 2c2c06c..9e6cee6 100644 --- a/include/protocol.h +++ b/include/protocol.h @@ -309,6 +309,16 @@ struct gg_userlist100_request { /* char request[]; */ } GG_PACKED; +#define GG_USERLIST100_REPLY 0x41 + +struct gg_userlist100_reply { + uint8_t type; /* rodzaj odpowiedzi */ + uint32_t version; /* numer wersji listy kontaktów aktualnie przechowywanej przez serwer */ + uint8_t format_type;/* rodzaj przesyłanego typu formatu listy kontaktów */ + uint8_t unknown1; /* 0x01 */ + /* char reply[]; */ +} GG_PACKED; + #ifdef _WIN32 #pragma pack(pop) #endif diff --git a/src/common.c b/src/common.c index 79fcbb0..9fb2743 100644 --- a/src/common.c +++ b/src/common.c @@ -671,6 +671,93 @@ fail: } /** + * \internal Dekompresuje dane wejściowe w formacie Deflate. + * + * Wynik funkcji należy zwolnić za pomocą \c free. + * + * \param in Bufor danych skompresowanych algorytmem Deflate + * \param length Długość bufora wejściowego + * + * \note Dokleja \c \\0 na końcu bufora wynikowego. + * + * \return Zdekompresowany ciąg znaków, zakończony \c
Re: [libgadu-devel] [PATCH 0/5] Obsługa eksportu i importu listy kontaktów Nowego Gadu-Gadu
W dniu 23 kwietnia 2011 16:53 użytkownik Wojtek Kaniewski wojte...@toxygen.net napisał: Świetnie! Jedna uwaga -- wszystko, co dotyczy protokołu, powinno trafić do protocol.h, a funkcje wewnętrzne biblioteki do internal.h. Nie chcemy zaśmiecać API/ABI rzeczami, które użytkowników nie dotyczą. Oczywiście jeśli nie masz czasu/ochoty, sam to poprawię, więc nie ma problemu. Poprawiłem to w wersjach v2 łatek nr 3 i 4. Mam nadzieję, że teraz jest w porządku. Pozdrawiam, Bartosz ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
[libgadu-devel] [PATCH 1/5] Aktualizacja opisu protokołu o opis eksportu i importu listy kontaktów sposobem Nowego Gadu-Gadu
--- docs/protocol.html | 110 +--- 1 files changed, 79 insertions(+), 31 deletions(-) diff --git a/docs/protocol.html b/docs/protocol.html index dc9982b..1141ffa 100644 --- a/docs/protocol.html +++ b/docs/protocol.html @@ -1496,10 +1496,13 @@ użyć pakietu: /p div class=c -pre#define GG_USERLIST_REQUEST80 0x002f +pre#define GG_USERLIST100_REQUEST 0x0040 -struct gg_userlist_request { +struct gg_userlist100_request { char type; i/* rodzaj zapytania *//i + int version;i/* numer ostatniej znanej wersji listy kontaktów bądź 0 *//i + char format_type; i/* rodzaj formatu listy kontaktów *//i + char unknown1; i/* zawsze 0x01 *//i char request[]; i/* treść (nie musi wystąpić) *//i };/pre /div @@ -1509,25 +1512,34 @@ Pole tttype/tt oznacza rodzaj zapytania: /p div class=c -pre#define GG_USERLIST_PUT 0x00i/* początek eksportu listy *//i -#define GG_USERLIST_PUT_MORE 0x01 i/* dalsza część eksportu listy *//i -#define GG_USERLIST_GET 0x02i/* import listy *//i/pre +pre#define GG_USERLIST100_PUT 0x00 i/* eksport listy *//i +#define GG_USERLIST100_GET 0x02i/* import listy *//i/pre /div p -W przypadku eksportu listy kontaktów, pole ttrequest/tt zawiera dokument -XML opisany na stronie -a href=http://dev.gadu-gadu.pl/api/pages/formaty_plikow.html;http://dev.gadu-gadu.pl/api/pages/formaty_plikow.html/a skompresowany algorytmem -a href=http://pl.wikipedia.org/wiki/Deflate;Deflate/a. Wolnodostępna -implementacja algorytmu, używana również przez oryginalnego klienta, znajduje -się w biblotece a href=http://www.zlib.net/;zlib/a. +Pole ttformat_type/tt oznacza typ formatu listy kontaktów: +/p + +div class=c +pre#define GG_USERLIST100_FORMAT_TYPE_NONE 0x00i/* brak treści listy kontaktów *//i +#define GG_USERLIST100_FORMAT_TYPE_GG70 0x01i/* format listy kontaktów zgodny z Gadu-Gadu 7.0 *//i +#define GG_USERLIST100_FORMAT_TYPE_GG100 0x02 i/* format listy kontaktów zgodny z Gadu-Gadu 10.0 *//i +/div + +p +Typ ttGG_USERLIST100_FORMAT_TYPE_NONE/tt ma sens wyłącznie w przypadku +importu listy kontaktów. Po jego użyciu serwer wysyła odpowiedź zawierającą +numer wersji listy kontaktów, ale bez samej listy kontaktów. Oryginalny klient +jednak w ogóle nie wykorzystuje tego sposobu. /p p -Podczas przesyłania lista kontaktów jest dzielona na pakiety po 2048 bajtów. -Pierwszy jest wysyłany pakietem typu ttGG_USERLIST_PUT/tt, żeby uaktualnić -plik na serwerze, pozostałe typu ttGG_USERLIST_PUT_MORE/tt, żeby dopisać -do pliku. +W przypadku eksportu listy kontaktów, pole ttrequest/tt, o ile zdefiniowano typ jako ttGG_USERLIST100_FORMAT_TYPE_GG100/tt, zawiera dokument +XML opisany na stronie +a href=http://dev.gadu-gadu.pl/api/pages/formaty_plikow.html;http://dev.gadu-gadu.pl/api/pages/formaty_plikow.html/a. Zawartość tego pola musi być skompresowana algorytmem +a href=http://pl.wikipedia.org/wiki/Deflate;Deflate/a. Wolnodostępna +implementacja algorytmu, używana również przez oryginalnego klienta, znajduje +się w biblotece a href=http://www.zlib.net/;zlib/a. Oryginalny klient używa najwyższego stopnia kompresji. /p p @@ -1535,10 +1547,13 @@ Na zapytania dotyczące listy kontaktów serwer odpowiada pakietem: /p div class=c -pre#define GG_USERLIST_REPLY80 0x0030 +pre#define GG_USERLIST100_REPLY 0x0041 -struct gg_userlist_reply { - char type; i/* rodzaj zapytania *//i +struct gg_userlist100_reply { + char type; i/* rodzaj odpowiedzi *//i + int version;i/* numer wersji listy kontaktów aktualnie przechowywanej przez serwer *//i + char format_type; i/* rodzaj przesyłanego typu formatu listy kontaktów *//i + char unknown1; i/* zawsze 0x01 *//i char reply[]; i/* treść (nie musi wystąpić) *//i };/pre /div @@ -1548,20 +1563,21 @@ Pole tttype/tt oznacza rodzaj odpowiedzi: /p div class=c -pre#define GG_USERLIST_PUT_REPLY 0x00 i/* początek eksportu listy *//i -#define GG_USERLIST_PUT_MORE_REPLY 0x02i/* kontynuacja *//i -#define GG_USERLIST_GET_MORE_REPLY 0x04i/* początek importu listy *//i -#define GG_USERLIST_GET_REPLY 0x06 i/* ostatnia część importu *//i/pre +pre#define GG_USERLIST100_REPLY_LIST 0x00 i/* w odpowiedzi znajduje się aktualna lista kontaktów na serwerze *//i +#define GG_USERLIST100_REPLY_ACK 0x10i/* potwierdzenie odebrania nowej wersji listy kontaktów *//i +#define GG_USERLIST100_REPLY_REJECT 0x12 i/* odmowa przyjęcia nowej wersji listy kontaktów z powodu +niezgodności numeru wersji listy kontaktów *//i/pre /div p -W przypadku importu w polu ttrequest/tt znajdzie się lista kontaktów -w takiej samej postaci, w jakiej ją umieszczono. Serwer nie ingeruje w jej -treść. Podobnie
[libgadu-devel] [PATCH 2/5] Kosmetyczne poprawki komentarzy dla GG_USERLIST100_VERSION
--- include/libgadu.h.in |4 ++-- include/protocol.h |2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/libgadu.h.in b/include/libgadu.h.in index 142e1ea..fb1d5ef 100644 --- a/include/libgadu.h.in +++ b/include/libgadu.h.in @@ -696,7 +696,7 @@ enum gg_event_t { GG_EVENT_MULTILOGON_MSG,/** Wiadomość wysłana z innej sesji multilogowania */ GG_EVENT_MULTILOGON_INFO, /** Informacja o innych sesjach multilogowania */ - GG_EVENT_USERLIST100_VERSION, /** Otrzymano numer wersji listy kontaktów na serwerze */ + GG_EVENT_USERLIST100_VERSION, /** Otrzymano numer wersji listy kontaktów na serwerze (10.0) */ }; #define GG_EVENT_SEARCH50_REPLY GG_EVENT_PUBDIR50_SEARCH_REPLY @@ -990,7 +990,7 @@ struct gg_event_multilogon_info { * Opis zdarzenia \c GG_EVENT_USERLIST100_VERSION. */ struct gg_event_userlist100_version { - uint32_t version; /** numer wersji listy kontaktów na serwerze */ + uint32_t version; /** Numer wersji listy kontaktów na serwerze */ }; /** diff --git a/include/protocol.h b/include/protocol.h index 157cbf4..b0b4fde 100644 --- a/include/protocol.h +++ b/include/protocol.h @@ -296,7 +296,7 @@ struct gg_dcc7_welcome_p2p { #define GG_USERLIST100_VERSION 0x5c struct gg_userlist100_version { - uint32_t version; + uint32_t version; /* numer wersji listy kontaktów */ } GG_PACKED; #ifdef _WIN32 -- 1.7.5.rc1 ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
[libgadu-devel] [PATCH 3/5] Dodanie obsługi pakietu GG_USERLIST100_REQUEST wraz z obsługą kompresji za pomocą zlib
Sprawdzanie zlib w configure.ac wymaga poprawki przez kogoś zaznajomionego z autotools. Sam nie mam pojęcia o autotools i zrobiłem to tylko tak, żeby na moim systemie libgadu w ogóle chciało się linkować ;). --- configure.ac |4 ++ include/libgadu.h.in | 53 src/common.c | 94 ++ src/libgadu.c| 64 ++ src/libgadu.sym |1 + 5 files changed, 216 insertions(+), 0 deletions(-) diff --git a/configure.ac b/configure.ac index ec4d048..e83c1e5 100644 --- a/configure.ac +++ b/configure.ac @@ -194,6 +194,10 @@ if test x$with_pthread = xyes; then AC_DEFINE([GG_CONFIG_PTHREAD_DEFAULT], [], [Defined if pthread resolver is the default one.]) fi +dnl zlib (TODO!) + +LIBS=$LIBS -lz + dnl dnl Sprawdzamy GnuTLS dnl diff --git a/include/libgadu.h.in b/include/libgadu.h.in index fb1d5ef..a785809 100644 --- a/include/libgadu.h.in +++ b/include/libgadu.h.in @@ -623,12 +623,15 @@ int gg_send_message_confer_richtext(struct gg_session *sess, int msgclass, int r int gg_send_message_ctcp(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, int message_len); int gg_ping(struct gg_session *sess); int gg_userlist_request(struct gg_session *sess, char type, const char *request); +int gg_userlist100_request(struct gg_session *sess, char type, unsigned int version, char format_type, const char *request); int gg_image_request(struct gg_session *sess, uin_t recipient, int size, uint32_t crc32); int gg_image_reply(struct gg_session *sess, uin_t recipient, const char *filename, const char *image, int size); int gg_typing_notification(struct gg_session *sess, uin_t recipient, int length); uint32_t gg_crc32(uint32_t crc, const unsigned char *buf, int len); +unsigned char *gg_deflate(const char *in, size_t *out_lenp); + int gg_session_set_resolver(struct gg_session *gs, gg_resolver_t type); gg_resolver_t gg_session_get_resolver(struct gg_session *gs); int gg_session_set_custom_resolver(struct gg_session *gs, int (*resolver_start)(int*, void**, const char*), void (*resolver_cleanup)(void**, int)); @@ -2030,6 +2033,8 @@ struct gg_recv_msg { #define GG_USERLIST_REQUEST 0x0016 +#define GG_USERLIST100_REQUEST 0x0040 + #define GG_XML_EVENT 0x0027 #ifndef DOXYGEN @@ -2083,6 +2088,54 @@ struct gg_userlist_reply { uint8_t type; } GG_PACKED; +#ifndef DOXYGEN + +#define GG_USERLIST100_PUT 0x00 +#define GG_USERLIST100_GET 0x02 + +#else + +/** + * \ingroup importexport + * + * Rodzaj zapytania (10.0). + */ +enum { + GG_USERLIST100_PUT, /** Eksport listy kontaktów. */ + GG_USERLIST100_GET, /** Import listy kontaktów. */ +}; + +#endif /* DOXYGEN */ + +#ifndef DOXYGEN + +#define GG_USERLIST100_FORMAT_TYPE_NONE 0x00 +#define GG_USERLIST100_FORMAT_TYPE_GG70 0x01 +#define GG_USERLIST100_FORMAT_TYPE_GG100 0x02 + +#else + +/** + * \ingroup importexport + * + * Typ formatu listy kontaktów (10.0). + */ +enum { + GG_USERLIST100_FORMAT_TYPE_NONE,/** Brak treści listy kontaktów. */ + GG_USERLIST100_FORMAT_TYPE_GG70,/** Format listy kontaktów zgodny z Gadu-Gadu 7.0. */ + GG_USERLIST100_FORMAT_TYPE_GG100, /** Format listy kontaktów zgodny z Gadu-Gadu 10.0. */ +}; + +#endif /* DOXYGEN */ + +struct gg_userlist100_request { + uint8_t type; /* rodzaj żądania */ + uint32_t version; /* numer ostatniej znanej wersji listy kontaktów bądź 0 */ + uint8_t format_type;/* rodzaj żądanego typu formatu listy kontaktów */ + uint8_t unknown1; /* 0x01 */ + /* char request[]; */ +} GG_PACKED; + struct gg_dcc_tiny_packet { uint8_t type; /* rodzaj pakietu */ } GG_PACKED; diff --git a/src/common.c b/src/common.c index 55e77d9..3951c47 100644 --- a/src/common.c +++ b/src/common.c @@ -42,6 +42,8 @@ #include string.h #include unistd.h +#include zlib.h + #include libgadu.h /** @@ -576,6 +578,98 @@ char *gg_proxy_auth(void) } /** + * \internal Kompresuje dane wejściowe algorytmem Deflate z najwyższym + * stopniem kompresji, tak samo jak oryginalny klient. + * + * Wynik funkcji należy zwolnić za pomocą \c free. + * + * \param in Ciąg znaków do skompresowania, zakończony \c \\0 + * \param out_lenp Wskaźnik na zmienną, do której zostanie zapisana + * długość bufora wynikowego + * + * \return Skompresowany ciąg znaków lub \c NULL w przypadku niepowodzenia. + */ +unsigned char *gg_deflate(const char *in, size_t *out_lenp) +{ + int ret; + z_stream strm; + unsigned char *out, *out2; + size_t out_len; + + if (in == NULL || out_lenp == NULL) + return NULL; + + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = strlen(in); + strm.next_in = (unsigned char*) in; + + ret =
[libgadu-devel] [PATCH 5/5] Aktualizacja dokumentacji grupy importexport
--- docs/importexport.dox | 31 --- 1 files changed, 20 insertions(+), 11 deletions(-) diff --git a/docs/importexport.dox b/docs/importexport.dox index 0554f41..31e7c67 100644 --- a/docs/importexport.dox +++ b/docs/importexport.dox @@ -7,27 +7,36 @@ Serwer pozwala przechowywać kompletną listę kontaktów w postaci tekstowej, by móc z niej korzystać na dowolnym komputerze bez konieczności ręcznego -przenoszenia. Standardowo format listy kontaktów jest narzucony przez -oryginalnego klienta (pola oddzielone średnikami), lecz serwer nie zwraca -uwagi na treść i można przechowywać dowolne dane, dopóki nie będą one pobierane -oryginalnym klientem. +przenoszenia. Format listy kontaktów jest narzucony przez oryginalnego klienta +(obecnie istnieją dwa wspierane formaty: pola oddzielone średnikami oraz dokument +XML). W celu sprawnej synchronizacji listy kontaktów między różnymi instalacjami +klienta sieci, serwer wersjonuje listę kontaktów i pozwala ją nadpisać tylko +w przypadku, gdy zadeklarujemy znajomość jej ostatniej wersji. -Aby wysłać wyeksportować kontaktów, wywołujemy: +Aby wysłać listę kontaktów, wywołujemy: \code -gg_userlist_request(sesja, GG_USERLIST_PUT, lista_kontatów); +gg_userlist100_request(sesja, GG_USERLIST100_PUT, wersja_listy_kontaktów, typ_formatu_listy_kontaktów, lista_kontatów); \endcode -W odpowiedzi dostaniemy od serwera zdarzenie \c GG_EVENT_USERLIST z polem -\c type równym \c GG_USERLIST_PUT_REPLY. +W odpowiedzi dostaniemy od serwera zdarzenie \c GG_EVENT_USERLIST100_REPLY z polem +\c type równym \c GG_USERLIST100_REPLY_ACK w przypadku akceptacji wysłanej listy +kontaktów lub \c GG_USERLIST100_REPLY_REJECT w przypadku jej odrzucenia. Pole +\c version zawiera numer aktualnie przechowywanej przez serwer listy kontaktów +(w przypadku przyjęcia nowej, jest to numer tej nowej wersji). Jeśli chcemy pobrać listę kontaktów z serwera, wywołujemy: \code -gg_userlist_request(sesja, GG_USERLIST_GET, NULL); +gg_userlist100_request(sesja, GG_USERLIST100_GET, 0, typ_formatu_listy_kontaktów, NULL); \endcode -Oczekujemy zdarzenia \c GG_EVENT_USERLIST z \c type równym -\c GG_USERLIST_GET_REPLY. Zawartość listy kontaktów znajdziemy w polu \c reply. +Oczekujemy zdarzenia \c GG_EVENT_USERLIST100_REPLY z \c type równym +\c GG_USERLIST100_REPLY_LIST. Zawartość listy kontaktów znajdziemy w polu \c reply, +a jej wersję w polu \c version. + +Ponadto możemy dostać od serwera informację o nowej wersji listy kontaktów. Wówczas +dostaniemy zdarzenie \c GG_EVENT_USERLIST100_VERSION z polem \c version równym numerowi +nowej wersji listy konktaktów. */ -- 1.7.5.rc1 ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] libgadu 1.10 i problemy z wysyłaniem obrazków
W dniu 6 marca 2011 22:57 użytkownik Bartosz Brachaczek b.brachac...@gmail.com napisał: Witam, Po aktualizacji libgadu do wersji 1.10.0 zauważyłem problemy z wysyłaniem obrazków. Używam Kadu w wersji z git master (z resolverem pthreads z libgadu). Problemy objawiają się tym, że zazwyczaj przy próbie wysłania obrazka Kadu się rozłącza, a rozmówca dostaje informację o przychodzącym obrazku, lecz ten nigdy do niego faktycznie nie dochodzi. Czasem jednak Kadu się nie rozłącza (tak przynajmniej mi się wydaje), ale obrazek i tak nie dochodzi. Czasami udaje się wysłać poprawnie obrazek. Z libgadu 1.9.1 nie ma żadnego problemu. Załączam archiwum z kilkoma logami. Nazwy plików, mam nadzieję, same się wyjaśniają. W każdej próbie wysyłałem inny obrazek jpg, każdy o rozmiarze 530x333 px i wadze ok. 40,4 KiB. Pozdrawiam, Bartosz Brachaczek Problem został potwierdzony przez dwóch użytkowników Kadu. Ja potestowałem co nieco SVN-a i na gałęzi 1.10 w wersji r1059 problem nadal występuje, a pojawił się on niestety w wersji r1037 Dalsza część merge'owania /branches/new-api. Próbowałem również samą gałąź new-api i tam do wersji r996 włącznie jest w porządku, ale od następnej (czyli r1008) żadna nie łączy mi się z siecią GG (nie dociekałem powodu). Pozdrawiam, Bartosz ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
Re: [libgadu-devel] Resend: [ekg-users] statyczna ana liza kodu libgadu/ekg z użyciem clang
Sądzę, że nie trzeba będzie tego debugować. Zgłaszający błąd napisał, że używa PCLinuxOS. Sprawdziłem więc, jak wygląda RPM dla libgadu-1.9.1 i okazuje się, że oni na źródła 1.9.1 (sic!) nakładają taką łatę: diff -Naur libgadu-1.9.0//src/events.c libgadu-1.9.0.tpg//src/events.c --- libgadu-1.9.0//src/events.c 2009-10-12 21:42:53.0 + +++ libgadu-1.9.0.tpg//src/events.c 2010-07-15 17:25:55.0 + @@ -69,6 +69,7 @@ switch (e-type) { case GG_EVENT_MSG: + free(e-event.msg.xhtml_message); free(e-event.msg.message); free(e-event.msg.formats); free(e-event.msg.recipients); Podczas gdy w źródłach 1.9.1 zwolnienie xhtml_message jest na końcu tego case'a, czego w tym diffie nie widać. W efekcie powstaje taki kod: switch (e-type) { case GG_EVENT_MSG: free(e-event.msg.xhtml_message); /* ! */ free(e-event.msg.message); free(e-event.msg.formats); free(e-event.msg.recipients); free(e-event.msg.xhtml_message); /* ! */ break; Co wyjaśnia narzekanie glibc na double free oraz fakt, że ręcznie skompilowane libgadu działa. Dzisiaj na IRC-u kolejny użytkownik zgłaszał podobny problem na Mandrivie, więc tam prawdopodobnie zrobili to samo. Ta sytuacja poważnie zmniejszyła moje uznanie dla paczkujących. Co za nieprofesjonalizm! Pozdrawiam, Bartosz Brachaczek ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel
[libgadu-devel] Integracja brancha dcc7-relay
Witam, Chciałbym się dowiedzieć, jakie są szanse na integrację brancha dcc7-relay z łatkami Bartłomieja Zimonia? Na podstawie wiadomości Wojtka Kaniewskiego z maja[1] wnioskuję, że mogłyby one wejść do kodu jeszcze w 1.9.x (1.9.2?). [1] http://lists.ziew.org/pipermail/libgadu-devel/2010-May/000623.html Pozdrawiam, Bartosz Brachaczek ___ libgadu-devel mailing list libgadu-devel@lists.ziew.org http://lists.ziew.org/mailman/listinfo/libgadu-devel