18 | Piotr Mach [pm]
19 | Rafał Malinowski
20 | Arkadiusz Miśkiewicz
21 | Marcin Owsiany
22 | Marcin Ślusarz
23 | Tomasz Wasilczyk
24 | Adam Wysocki
25 | Piotr Wysocki
26 | Jakub Zawadzki
27 |
28 | Marek Antoniak
29 | Michał Bartoszkiewicz
30 | Wojciech Bojdoł
31 | Artur Gawryszczak
32 | Krzysztof Gibas [sdas]
33 | Stanisław Gurgacz
34 | Rafał Janiczek
35 | Marcin Mikuła
36 | Jacek Osiecki
37 | Adam Osuchowski
38 | Paweł Pruszkowski
39 | Adrian Smarzewski
40 | Adam Strzelecki
41 | Szymon Zygmunt
42 |
43 | Wykorzystano kod udostępniony na zasadach domeny publicznej autorstwa:
44 |
45 | Steve Reid
46 |
--------------------------------------------------------------------------------
/docs/importexport.dox:
--------------------------------------------------------------------------------
1 | /**
2 |
3 | \defgroup importexport Import i eksport listy kontaktów
4 | \ingroup session
5 |
6 | \details
7 |
8 | Serwer pozwala przechowywać kompletną listę kontaktów w postaci tekstowej,
9 | by móc z niej korzystać na dowolnym komputerze bez konieczności ręcznego
10 | przenoszenia. Format listy kontaktów jest narzucony przez oryginalnego klienta
11 | (obecnie istnieją dwa wspierane formaty: pola oddzielone średnikami oraz dokument
12 | XML). W celu sprawnej synchronizacji listy kontaktów między różnymi instalacjami
13 | klienta sieci, serwer wersjonuje listę kontaktów i pozwala ją nadpisać tylko
14 | w przypadku, gdy zadeklarujemy znajomość jej ostatniej wersji.
15 |
16 | Aby wysłać listę kontaktów, wywołujemy:
17 |
18 | \code
19 | gg_userlist100_request(sesja, GG_USERLIST100_PUT, wersja_listy_kontaktów, typ_formatu_listy_kontaktów, lista_kontatów);
20 | \endcode
21 |
22 | W odpowiedzi dostaniemy od serwera zdarzenie \c GG_EVENT_USERLIST100_REPLY z polem
23 | \c type równym \c GG_USERLIST100_REPLY_ACK w przypadku akceptacji wysłanej listy
24 | kontaktów lub \c GG_USERLIST100_REPLY_REJECT w przypadku jej odrzucenia. Pole
25 | \c version zawiera numer aktualnie przechowywanej przez serwer listy kontaktów
26 | (w przypadku przyjęcia nowej, jest to numer tej nowej wersji).
27 |
28 | Jeśli chcemy pobrać listę kontaktów z serwera, wywołujemy:
29 |
30 | \code
31 | gg_userlist100_request(sesja, GG_USERLIST100_GET, 0, typ_formatu_listy_kontaktów, NULL);
32 | \endcode
33 |
34 | Oczekujemy zdarzenia \c GG_EVENT_USERLIST100_REPLY z \c type równym
35 | \c GG_USERLIST100_REPLY_LIST. Zawartość listy kontaktów znajdziemy w polu \c reply,
36 | a jej wersję w polu \c version.
37 |
38 | Ponadto możemy dostać od serwera informację o nowej wersji listy kontaktów. Wówczas
39 | dostaniemy zdarzenie \c GG_EVENT_USERLIST100_VERSION z polem \c version równym numerowi
40 | nowej wersji listy konktaktów.
41 |
42 | */
43 |
--------------------------------------------------------------------------------
/docs/http.dox:
--------------------------------------------------------------------------------
1 | /**
2 |
3 | \defgroup http Usługi HTTP
4 | \ingroup services
5 |
6 | \details
7 |
8 | Obecnie wszystkie usługi dodatkowe są realizowane za pomocą protokołu HTTP.
9 | Przy operacjach synchronicznych należy jedynie wywołać funkcję, sprawdzić kod
10 | błędu i jeśli operacja się powiodła, należy odczytać wynik funkcji
11 | z odpowiedniej struktury.
12 |
13 | Operacje asynchroniczne różnią się od zwykłych połączeń z serwerem jedynie
14 | tym, że zakończenie operacji jest określane przez pole \c state, które
15 | przyjmuje wartość \c GG_STATE_DONE w przypadku sukcesu lub
16 | \c GG_STATE_ERROR w przypadku błędu. Podobnie jak w przypadku połączenia
17 | z serwerem, należy wywoływać funkcję \c gg_http_watch_fd() po zaobserwowaniu
18 | zmian na określonym deskryptorze.
19 |
20 | Każdą operację asynchroniczną można ponadto zatrzymać w trakcie działania
21 | za pomocą funkcji \c gg_http_stop().
22 |
23 | Część operacji związanych z katalogiem publicznym w polu \c data struktury
24 | \c gg_http przekazuje strukturę \c gg_pubdir zawierającą wynik danej operacji.
25 | Szczegóły znajdują się na stronach poszczególnych usług dodatkowych.
26 |
27 | \defgroup register Rejestracja nowego użytkownika
28 | \ingroup services
29 |
30 | \details
31 |
32 | Po zakończeniu operacji, pole \c data struktury \c gg_http zawiera wskaźnik do
33 | struktury \c gg_pubdir. Ta ostatnia w polu \c success określa, czy operacja się
34 | powiodła. Jeśli tak, to w polu \c uin znajdzie się zarejestrowany numer.
35 |
36 | \defgroup passwd Zmiana hasła
37 | \ingroup services
38 |
39 | \details
40 |
41 | Po zakończeniu operacji, pole \c data struktury \c gg_http zawiera wskaźnik do
42 | struktury \c gg_pubdir. Ta ostatnia w polu \c success określa, czy operacja się
43 | powiodła.
44 |
45 | \defgroup unregister Usuwanie użytkownika
46 | \ingroup services
47 |
48 | \copydoc passwd
49 |
50 | \defgroup remind Przypomnienie hasła
51 | \ingroup services
52 |
53 | \copydoc passwd
54 | */
55 |
--------------------------------------------------------------------------------
/test/automatic/endian1.c:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2001-2006 Wojtek Kaniewski
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License Version
6 | * 2.1 as published by the Free Software Foundation.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU Lesser General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU Lesser General Public
14 | * License along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
16 | * USA.
17 | */
18 |
19 | #include "internal.h"
20 |
21 | #include
22 | #include
23 | #include
24 |
25 | static void test_gg_fix64(void)
26 | {
27 | const char *source = "\xff\xee\xdd\xcc\xbb\xaa\x99\x88";
28 | uint64_t value;
29 |
30 | memcpy(&value, source, sizeof(value));
31 |
32 | if (gg_fix64(value) != 0x8899aabbccddeeffLL) {
33 | fprintf(stderr, "gg_fix64 failed\n");
34 | exit(1);
35 | }
36 | }
37 |
38 | static void test_gg_fix32(void)
39 | {
40 | const char *source = "\xee\xdd\xcc\xbb";
41 | uint32_t value;
42 |
43 | memcpy(&value, source, sizeof(value));
44 |
45 | if (gg_fix32(value) != 0xbbccddee) {
46 | fprintf(stderr, "gg_fix32 failed\n");
47 | exit(1);
48 | }
49 | }
50 |
51 | static void test_gg_fix16(void)
52 | {
53 | const char *source = "\xdd\xcc";
54 | uint16_t value;
55 |
56 | memcpy(&value, source, sizeof(value));
57 |
58 | if (gg_fix16(value) != 0xccdd) {
59 | fprintf(stderr, "gg_fix16 failed\n");
60 | exit(1);
61 | }
62 | }
63 |
64 | int main(void)
65 | {
66 | test_gg_fix64();
67 | test_gg_fix32();
68 | test_gg_fix16();
69 |
70 | return 0;
71 | }
72 |
--------------------------------------------------------------------------------
/include/fileio.h:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2011 Bartosz Brachaczek
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License Version
6 | * 2.1 as published by the Free Software Foundation.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU Lesser General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU Lesser General Public
14 | * License along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
16 | * USA.
17 | */
18 |
19 | /**
20 | * \file fileio.h
21 | *
22 | * \brief Makra zapewniające kompatybilność API do obsługi operacji na plikach na różnych systemach
23 | */
24 |
25 | #ifndef LIBGADU_FILEIO_H
26 | #define LIBGADU_FILEIO_H
27 |
28 | #ifdef LIBGADU_NETWORK_H
29 | # error "Always include fileio.h before network.h"
30 | #endif
31 |
32 | #include
33 | #include
34 | #include
35 |
36 | #ifdef _WIN32
37 | # include
38 | # define gg_file_close _close
39 | # undef lseek
40 | # define lseek _lseek
41 | # undef open
42 | # define open _open
43 | # undef read
44 | # define read _read
45 | # undef stat
46 | # define stat _stat
47 | # undef fstat
48 | # define fstat _fstat
49 | # undef write
50 | # define write _write
51 | # ifndef S_IRWXO
52 | # define S_IRWXO 0
53 | # endif
54 | # ifndef S_IRWXG
55 | # define S_IRWXG 0
56 | # endif
57 | #else
58 | # ifdef sun
59 | # include
60 | # endif
61 | # include
62 | # define gg_file_close close
63 | #endif
64 |
65 | #ifndef S_IWUSR
66 | # define S_IWUSR S_IWRITE
67 | #endif
68 |
69 | #endif /* LIBGADU_FILEIO_H */
70 |
--------------------------------------------------------------------------------
/test/automatic/Makefile.am:
--------------------------------------------------------------------------------
1 | TESTS = connect convert endian1 hash message1 message2 packet protocol resolver
2 |
3 | check_PROGRAMS = $(TESTS)
4 |
5 | AM_CPPFLAGS = -DGG_IGNORE_DEPRECATED -I$(top_srcdir)/include -I$(top_srcdir)/test
6 | AM_LDFLAGS = @LDFLAGS_NO_INSTALL@
7 |
8 | EXTRA_DIST = protocol.txt connect.txt connect.pem wine-wrapper.sh skipped.c
9 |
10 | if HAVE_PERL
11 | protocol_SOURCES = protocol.c
12 | nodist_protocol_SOURCES = script.c libgadu-network.c
13 | protocol_CFLAGS = -I$(top_srcdir)/test/automatic/script
14 | protocol_LDADD = $(top_builddir)/src/libgadu.la
15 | else
16 | EXTRA_DIST += protocol.c
17 | nodist_protocol_SOURCES = skipped.c
18 | endif
19 |
20 | convert_SOURCES = convert.c
21 | nodist_convert_SOURCES = libgadu-encoding.c
22 |
23 | message1_SOURCES = message1.c
24 |
25 | message2_SOURCES = message2.c
26 | nodist_message2_SOURCES = libgadu-message.c
27 | message2_LDADD = @LIBXML2_LIBS@
28 | message2_CFLAGS = @LIBXML2_CFLAGS@
29 |
30 | hash_SOURCES = hash.c
31 | nodist_hash_SOURCES = libgadu-sha1.c libgadu-endian.c
32 |
33 | endian1_SOURCES = endian1.c
34 | nodist_endian1_SOURCES = libgadu-endian.c
35 |
36 | if BUILD_CONNECT_TEST
37 | connect_SOURCES = connect.c
38 | nodist_connect_SOURCES = libgadu-network.c
39 | connect_LDADD = $(top_builddir)/src/libgadu.la @GNUTLS_LIBS@
40 | connect_CFLAGS = @GNUTLS_CFLAGS@
41 | else
42 | EXTRA_DIST += connect.c
43 | nodist_connect_SOURCES = skipped.c
44 | endif
45 |
46 | packet_LDADD = $(top_builddir)/src/libgadu.la
47 |
48 | resolver_LDADD = $(top_builddir)/src/libgadu.la
49 |
50 | SUBDIRS = script
51 |
52 | script.c: $(wildcard script/*.scr) script/compile
53 | $(AM_V_GEN)$(PERL) $(top_srcdir)/test/automatic/script/compile $(top_srcdir)/test/automatic/script/*.scr > script.c
54 |
55 | clean-local:
56 | rm -f *-valgrind.log *-valgrind script.c skipped.c libgadu-*.c
57 |
58 | check-local: $(check_PROGRAMS)
59 | for i in $(check_PROGRAMS); do ln -sf ../valgrind $${i}-valgrind; done
60 |
61 | libgadu-%.c: ../../src/%.c
62 | $(AM_V_GEN)cat "$<" > "$@"
63 |
64 | skipped.c:
65 | echo 'int main() { return 77; }' > $@
66 |
--------------------------------------------------------------------------------
/include/message.h:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2009 Wojtek Kaniewski
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License Version
6 | * 2.1 as published by the Free Software Foundation.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU Lesser General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU Lesser General Public
14 | * License along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
16 | * USA.
17 | */
18 |
19 | #ifndef LIBGADU_MESSAGE_H
20 | #define LIBGADU_MESSAGE_H
21 |
22 | #include
23 | #include "libgadu.h"
24 |
25 | #if 0
26 |
27 | struct gg_message {
28 | uin_t *recipients;
29 | size_t recipient_count;
30 | char *text;
31 | char *html;
32 | char *attributes;
33 | size_t attributes_length;
34 | uint32_t msgclass;
35 | uint32_t seq;
36 |
37 | int auto_convert;
38 | char *text_converted;
39 | char *html_converted;
40 | };
41 |
42 | #define GG_MESSAGE_CHECK(gm, result) \
43 | if ((gm) == NULL) { \
44 | errno = EINVAL; \
45 | return (result); \
46 | }
47 |
48 | int gg_message_init(gg_message_t *gm, int msgclass, int seq, uin_t *recipients,
49 | size_t recipient_count, char *text, char *xhtml, char *attributes,
50 | size_t attributes_length, int auto_convert);
51 |
52 | #endif
53 |
54 | size_t gg_message_html_to_text(char *dst, unsigned char *format,
55 | size_t *format_len, const char *html, gg_encoding_t encoding);
56 | size_t gg_message_text_to_html(char *dst, const char *src,
57 | gg_encoding_t encoding, const unsigned char *format, size_t format_len);
58 |
59 | char * gg_message_html_to_text_110(const char *html);
60 | char * gg_message_text_to_html_110(const char *text, ssize_t text_len);
61 |
62 | #endif /* LIBGADU_MESSAGE_H */
63 |
--------------------------------------------------------------------------------
/include/tvbuilder.h:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2012 Tomek Wasilczyk
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License Version
6 | * 2.1 as published by the Free Software Foundation.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU Lesser General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU Lesser General Public
14 | * License along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
16 | * USA.
17 | */
18 |
19 | #ifndef LIBGADU_TVBUILDER_H
20 | #define LIBGADU_TVBUILDER_H
21 |
22 | #include "libgadu.h"
23 |
24 | typedef struct gg_tvbuilder gg_tvbuilder_t;
25 |
26 | gg_tvbuilder_t * gg_tvbuilder_new(struct gg_session *gs, struct gg_event *ge);
27 | void gg_tvbuilder_free(gg_tvbuilder_t *tvb);
28 | void gg_tvbuilder_fail(gg_tvbuilder_t *tvb, enum gg_failure_t failure);
29 | int gg_tvbuilder_send(gg_tvbuilder_t *tvb, int type);
30 |
31 | int gg_tvbuilder_is_valid(const gg_tvbuilder_t *tvb);
32 |
33 | size_t gg_tvbuilder_get_size(const gg_tvbuilder_t *tvb);
34 | void gg_tvbuilder_expected_size(gg_tvbuilder_t *tvb, size_t length);
35 | void gg_tvbuilder_strip(gg_tvbuilder_t *tvb, size_t length);
36 |
37 | void gg_tvbuilder_write_uint8(gg_tvbuilder_t *tvb, uint8_t value);
38 | void gg_tvbuilder_write_uint32(gg_tvbuilder_t *tvb, uint32_t value);
39 | void gg_tvbuilder_write_uint64(gg_tvbuilder_t *tvb, uint64_t value);
40 |
41 | void gg_tvbuilder_write_packed_uint(gg_tvbuilder_t *tvb, uint64_t value);
42 |
43 | void gg_tvbuilder_write_buff(gg_tvbuilder_t *tvb, const char *buffer, size_t length);
44 | void gg_tvbuilder_write_str(gg_tvbuilder_t *tvb, const char *buffer, ssize_t length);
45 |
46 | void gg_tvbuilder_write_uin(gg_tvbuilder_t *tvb, uin_t uin);
47 |
48 | #endif /* LIBGADU_TVBUILDER_H */
49 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | UWAGA!
2 | ======
3 |
4 | Ze względu na brak developmentu i spadek znaczenia Gadu-Gadu (kolejność
5 | przypadkowa) oficjalnie zamykamy projekt. Najpóźniej do końca 2025 roku
6 | repozytorium zostanie zarchiwizowane, tj. kod źródłowy i wydane wersje
7 | będą nadal dostępne, ale jedynie w trybie tylko do odczytu. Nie będzie
8 | można wprowadzać zmian, ani zgłaszać błędów, ale repozytorium będzie
9 | można forkować, jeśli zajdzie taka potrzeba. Oficjalna strona zostanie
10 | przeniesiona pod adres [libgadu.github.io](https://libgadu.github.io/), a domena libgadu.net nie
11 | będzie po 2025 roku opłacana. Dziękujemy wszystkim zaangażowanym
12 | w rozwój libgadu i klienta ekg, z którego biblioteka została wydzielona.
13 | Dla niektórych były to pierwsze poważne projekty open-source, pierwsze
14 | przygody z inżynierią wsteczną, pierwszy prawdziwie wieloplatformowy
15 | kod, pierwsze bug reporty, pierwsze publiczne ogłoszenia błędów
16 | bezpieczeństwa czy pierwszy kod trafiający do dystrybucji Linuksa.
17 | Cześć, i dzięki za ryby!
18 |
19 | Oryginalny plik [README](README) jest nadal dostępny.
20 |
21 | ATTENTION!
22 | ==========
23 |
24 | Due to lack of development and loss of importance of Gadu-Gadu (in
25 | random order) the project is officially closed. Until the end of 2025
26 | the repository will be archived, i.e. source code and released versions
27 | will be still available, but only in read-only mode. Pushing commits and
28 | filing bug reports will not be possible, but forking will still be
29 | possible should there be need. The official website is moved to
30 | [libgadu.github.io](https://libgadu.github.io/), and the libgadu.net domain will not be renewed past
31 | 2025. Thank you to all the people involved in the development of libgadu
32 | and ekg client, from which the library was carved out. For some those
33 | were the first serious open-source projects, first adventures with
34 | reverse engineering, first multiplatform code, first bug reports, first
35 | security advisories or first code ending up in Linux distros. So Long,
36 | and Thanks for All the Fish!
37 |
38 | The original [README.en](README.en) file is still available.
39 |
--------------------------------------------------------------------------------
/test/automatic/script/script.h:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2001-2006 Wojtek Kaniewski
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License Version
6 | * 2.1 as published by the Free Software Foundation.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU Lesser General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU Lesser General Public
14 | * License along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
16 | * USA.
17 | */
18 |
19 | #ifndef SCRIPT_H
20 | #define SCRIPT_H
21 |
22 | #include "libgadu.h"
23 |
24 | typedef enum {
25 | ACTION_LOGIN = 1,
26 | ACTION_SEND,
27 | ACTION_END,
28 | ACTION_CALL,
29 | ACTION_LOGOFF,
30 | EXPECT_DATA,
31 | EXPECT_EVENT,
32 | EXPECT_CONNECT,
33 | EXPECT_DISCONNECT,
34 | } state_type_t;
35 |
36 | typedef int (*state_check_event_func_t)(int type, union gg_event_union *);
37 | typedef void (*state_api_call_func_t)(struct gg_session *);
38 |
39 | typedef struct {
40 | const char *filename;
41 | int line;
42 | int test;
43 | state_type_t type;
44 | struct gg_login_params *glp;
45 | int event;
46 | state_check_event_func_t check_event;
47 | state_api_call_func_t call;
48 | unsigned char *data;
49 | unsigned char *data_mask;
50 | int data_len;
51 | } state_t;
52 |
53 | extern state_t script[];
54 |
55 | extern const char *tests[];
56 |
57 | #ifdef _WIN32
58 | #define logon_time_t uint32_t
59 | #else
60 | #define logon_time_t time_t
61 | #endif
62 |
63 | #ifdef FALSE
64 | #undef FALSE
65 | #endif
66 | #define FALSE 0
67 |
68 | #ifdef TRUE
69 | #undef TRUE
70 | #endif
71 | #define TRUE 1
72 |
73 | #ifdef GG_CONFIG_BIGENDIAN
74 | #define ip(a, b, c, d) ((a)<<24|(b)<<16|(c)<<8|(d))
75 | #else
76 | #define ip(a, b, c, d) ((a)|(b)<<8|(c)<<16|(d)<<24)
77 | #endif
78 |
79 | #endif /* SCRIPT_H */
80 |
--------------------------------------------------------------------------------
/m4/openssl.m4:
--------------------------------------------------------------------------------
1 | dnl based on curses.m4
2 |
3 | AC_DEFUN([AC_CHECK_OPENSSL],[
4 | AC_SUBST(OPENSSL_LIBS)
5 | AC_SUBST(OPENSSL_INCLUDES)
6 |
7 | with_arg=""
8 |
9 | AC_ARG_WITH(openssl,
10 | [[ --with-openssl use OpenSSL, if found (the resulting binary won't be GPL-compliant)]],
11 | if test "x$withval" != "xyes" -a "x$withval" != "xno" ; then
12 | with_arg=$withval/include:-L$withval/lib
13 | with_openssl="yes"
14 | fi,
15 | with_openssl="no")
16 |
17 | if test "x$with_openssl" = "xyes" -a "x$with_arg" = "x"; then
18 | PKG_CHECK_MODULES([OPENSSL], [openssl >= 0.9.7], [
19 | AC_DEFINE(HAVE_OPENSSL, 1, [define if you have OpenSSL])
20 | without_openssl=yes
21 | have_openssl=yes
22 | ], [:])
23 | fi
24 |
25 | if test "x$with_openssl" = "xyes" -a "x$have_openssl" != "xyes" ; then
26 | dnl Beware, this code is not able to check installed openssl version
27 |
28 | AC_MSG_CHECKING(for ssl.h)
29 |
30 | for i in $with_arg \
31 | /usr/include: \
32 | /usr/local/include:"-L/usr/local/lib" \
33 | /usr/local/ssl/include:"-L/usr/local/ssl/lib" \
34 | /usr/pkg/include:"-L/usr/pkg/lib" \
35 | /usr/contrib/include:"-L/usr/contrib/lib" \
36 | /usr/freeware/include:"-L/usr/freeware/lib32" \
37 | /sw/include:"-L/sw/lib" \
38 | /cw/include:"-L/cw/lib" \
39 | /boot/home/config/include:"-L/boot/home/config/lib"; do
40 |
41 | incl=`echo "$i" | sed 's/:.*//'`
42 | lib=`echo "$i" | sed 's/.*://'`
43 |
44 | if test -f $incl/openssl/ssl.h; then
45 | AC_MSG_RESULT($incl/openssl/ssl.h)
46 | ldflags_old="$LDFLAGS"
47 | LDFLAGS="$lib -lssl -lcrypto"
48 | save_LIBS="$LIBS"
49 | LIBS="-lssl -lcrypto $LIBS"
50 | AC_CHECK_LIB(ssl, RSA_new, [
51 | AC_DEFINE(HAVE_OPENSSL, 1, [define if you have OpenSSL])
52 | have_openssl=yes
53 | OPENSSL_LIBS="$lib -lssl -lcrypto"
54 | if test "x$incl" != "x/usr/include"; then
55 | OPENSSL_INCLUDES="-I$incl"
56 | fi
57 | ])
58 | LIBS="$save_LIBS"
59 | LDFLAGS="$ldflags_old"
60 | break
61 | fi
62 | done
63 |
64 | if test "x$have_openssl" != "xyes"; then
65 | AC_MSG_RESULT(not found)
66 | fi
67 | fi
68 | ])
69 |
--------------------------------------------------------------------------------
/examples/status.c:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2001-2006 Wojtek Kaniewski
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License Version
6 | * 2.1 as published by the Free Software Foundation.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU Lesser General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU Lesser General Public
14 | * License along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
16 | * USA.
17 | */
18 |
19 | /*
20 | * przykład prostego programu łączącego się z serwerem i zmieniającego opis.
21 | */
22 |
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include "libgadu.h"
28 | #include "network.h"
29 |
30 | int main(int argc, char **argv)
31 | {
32 | struct gg_session *gs;
33 | struct gg_login_params glp;
34 |
35 | if (argc < 4) {
36 | fprintf(stderr, "użycie: %s \n", argv[0]);
37 | return 1;
38 | }
39 |
40 | #ifdef _WIN32
41 | gg_win32_init_network();
42 | #endif
43 |
44 | gg_debug_level = 255;
45 |
46 | memset(&glp, 0, sizeof(glp));
47 | glp.uin = atoi(argv[1]);
48 | glp.password = argv[2];
49 | #if 0
50 | glp.encoding = GG_ENCODING_UTF8;
51 | glp.protocol_version = GG_PROTOCOL_VERSION_110;
52 | #endif
53 | glp.status = GG_STATUS_INVISIBLE_DESCR;
54 | glp.status_descr = argv[3];
55 |
56 | if (!(gs = gg_login(&glp))) {
57 | printf("Nie udało się połączyć: %s\n", strerror(errno));
58 | gg_free_session(gs);
59 | return 1;
60 | }
61 |
62 | gg_notify(gs, NULL, 0);
63 |
64 | printf("Połączono.\n");
65 |
66 | if (gg_change_status_descr(gs, GG_STATUS_NOT_AVAIL_DESCR, argv[3]) == -1) {
67 | printf("Połączenie przerwane: %s\n", strerror(errno));
68 | gg_free_session(gs);
69 | return 1;
70 | }
71 |
72 | gg_logoff(gs);
73 | gg_free_session(gs);
74 |
75 | return 0;
76 | }
77 |
--------------------------------------------------------------------------------
/include/tvbuff.h:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2012 Tomek Wasilczyk
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License Version
6 | * 2.1 as published by the Free Software Foundation.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU Lesser General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU Lesser General Public
14 | * License along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
16 | * USA.
17 | */
18 |
19 | #ifndef LIBGADU_TVBUFF_H
20 | #define LIBGADU_TVBUFF_H
21 |
22 | #include "libgadu.h"
23 |
24 | typedef struct gg_tvbuff gg_tvbuff_t;
25 |
26 | gg_tvbuff_t * gg_tvbuff_new(const char *buffer, size_t length);
27 | int gg_tvbuff_close(gg_tvbuff_t *tvb);
28 |
29 | int gg_tvbuff_is_valid(const gg_tvbuff_t *tvb);
30 |
31 | size_t gg_tvbuff_get_remaining(const gg_tvbuff_t *tvb);
32 |
33 | int gg_tvbuff_have_remaining(gg_tvbuff_t *tvb, size_t length);
34 |
35 | void gg_tvbuff_skip(gg_tvbuff_t *tvb, size_t amount);
36 | void gg_tvbuff_rewind(gg_tvbuff_t *tvb, size_t amount);
37 |
38 | int gg_tvbuff_match(gg_tvbuff_t *tvb, uint8_t value);
39 |
40 | uint8_t gg_tvbuff_read_uint8(gg_tvbuff_t *tvb);
41 | uint32_t gg_tvbuff_read_uint32(gg_tvbuff_t *tvb);
42 | uint64_t gg_tvbuff_read_uint64(gg_tvbuff_t *tvb);
43 |
44 | uint64_t gg_tvbuff_read_packed_uint(gg_tvbuff_t *tvb);
45 |
46 | const char * gg_tvbuff_read_buff(gg_tvbuff_t *tvb, size_t length);
47 | void gg_tvbuff_read_buff_cpy(gg_tvbuff_t *tvb, char *buffer, size_t length);
48 | const char * gg_tvbuff_read_str(gg_tvbuff_t *tvb, size_t *length);
49 | void gg_tvbuff_read_str_dup(gg_tvbuff_t *tvb, char **dst);
50 |
51 | uin_t gg_tvbuff_read_uin(gg_tvbuff_t *tvb);
52 |
53 | void gg_tvbuff_expected_uint8(gg_tvbuff_t *tvb, uint8_t value);
54 | void gg_tvbuff_expected_uint32(gg_tvbuff_t *tvb, uint32_t value);
55 | void gg_tvbuff_expected_eob(const gg_tvbuff_t *tvb);
56 |
57 | #endif /* LIBGADU_TVBUFF_H */
58 |
--------------------------------------------------------------------------------
/include/session.h:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2008-2010 Wojtek Kaniewski
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License Version
6 | * 2.1 as published by the Free Software Foundation.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU Lesser General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU Lesser General Public
14 | * License along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
16 | * USA.
17 | */
18 |
19 | #ifndef LIBGADU_SESSION_H
20 | #define LIBGADU_SESSION_H
21 |
22 | #ifdef GG_CONFIG_HAVE_GNUTLS
23 | # include
24 | #endif
25 |
26 | #define GG_SESSION_CHECK(gs, result) \
27 | do { \
28 | if ((gs) == NULL) { \
29 | errno = EINVAL; \
30 | return (result); \
31 | } \
32 | } while (0)
33 |
34 | #define GG_SESSION_CHECK_CONNECTED(gs, result) \
35 | do { \
36 | GG_SESSION_CHECK(gs, result); \
37 | \
38 | if (!GG_SESSION_IS_CONNECTED(gs)) { \
39 | errno = ENOTCONN; \
40 | return (result); \
41 | } \
42 | } while (0)
43 |
44 | #define GG_SESSION_IS_IDLE(gs) ((gs)->state == GG_STATE_IDLE)
45 | #define GG_SESSION_IS_CONNECTING(gs) ((gs)->state != GG_STATE_IDLE && (gs)->state != GG_STATE_CONNECTED)
46 | #define GG_SESSION_IS_CONNECTED(gs) ((gs)->state == GG_STATE_CONNECTED)
47 |
48 | #ifdef GG_CONFIG_HAVE_GNUTLS
49 |
50 | typedef struct {
51 | int global_init_called;
52 | gnutls_session_t session;
53 | int session_ready;
54 | gnutls_certificate_credentials_t xcred;
55 | int xcred_ready;
56 | } gg_session_gnutls_t;
57 |
58 | #define GG_SESSION_GNUTLS(gs) ((gg_session_gnutls_t*) (gs)->ssl)->session
59 |
60 | #endif /* GG_CONFIG_HAVE_GNUTLS */
61 |
62 | #ifdef GG_CONFIG_HAVE_OPENSSL
63 |
64 | #define GG_SESSION_OPENSSL(gs) ((SSL*) (gs)->ssl)
65 |
66 | #endif /* GG_CONFIG_HAVE_OPENSSL */
67 |
68 | int gg_session_handle_packet(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge);
69 |
70 | #endif /* LIBGADU_SESSION_H */
71 |
--------------------------------------------------------------------------------
/docs/build.dox:
--------------------------------------------------------------------------------
1 | /**
2 |
3 | \defgroup build Kompilacja
4 |
5 | \details
6 |
7 | Kompilację biblioteki na systemach uniksowych lub uniksopodobnych (np. Windows +
8 | Cygwin) przeprowadza się według typowego schematu:
9 |
10 | \code
11 | $ ./configure
12 | $ make
13 | # make install
14 | \endcode
15 |
16 | Gdzie ostatnią komendę wykonuje się z prawami administratora. Aby zainstalować
17 | bibliotekę w katalogu użytkownika, można wykonać polecenia:
18 |
19 | \code
20 | $ ./configure --prefix=/katalog/użytkownika/libgadu
21 | $ make
22 | $ make install
23 | \endcode
24 |
25 | Następnie, aby użyć lokalnie zainstalowanej kopii biblioteki, zwykle należy
26 | dodać do zmiennej \c CFLAGS opcję \c -I/katalog/użytkownika/libgadu/include , a do \c LDFLAGS opcję \c -L/katalog/użytkownika/libgadu/lib.
27 |
28 | \section build-cross Kompilacja skrośna
29 |
30 | Przy kompilacji skrośnej konieczne jest użycie parametru
31 | \c --with-c99-vsnprintf lub \c --without-c99-vsnprintf w skrypcie \c configure,
32 | który mówi o tym, że funkcje rodziny \c sprintf() na docelowej platformie są
33 | zgodne lub niezgodne ze standardem C99. Jeśli żaden z powyższych parametrów
34 | nie zostanie użyty, skrypt \c configure spróbuje uruchomić program testowy,
35 | co przy kompilacji skrośnej się nie powiedzie.
36 |
37 | \section build-resolver Rozwiązywanie nazw
38 |
39 | Biblioteka oferuje dwa sposoby rozwiązywania nazw serwerów w trybie
40 | asynchronicznym: za pomocą osobnego procesu lub za pomocą osobnego wątku.
41 | Druga możliwość jest zalecana dla programów, które korzystają z wątków
42 | systemowych, ponieważ użycie funkcji \c fork() do tworzenia procesu potomnego
43 | w aplikacji korzystającej z wątków może powodować problemy. W wersjach
44 | wcześniejszych niż 1.9.0 sposób rozwiązywania nazw był wybierany na etapie
45 | kompilacji, co powodowało problemy, gdy w systemie były zainstalowane aplikacje
46 | korzystające i niekorzystające z wątków systemowych. Od wersji 1.9.0, jeśli
47 | jest to możliwe, kompilowane są obie wersje, a wybór jest dokonywany przez
48 | aplikację.
49 |
50 | Od wersji 1.12.0 domyślna metoda to \c GG_RESOLVER_PTHREAD (użycie wątków
51 | pthread), bez możliwości wybrania priorytetu na etapie kompilacji. Jeżeli ta
52 | jest niedostępna (lub zostanie wyłączona przełącznikiem \c --without-pthread),
53 | użyta zostanie -- w zależności od systemu -- \c GG_RESOLVER_WIN32 (użycie
54 | natywnych wątków win32) lub \c GG_RESOLVER_FORK (użycie osobnego procesu).
55 | W razie potrzeby można użyć własnej implementacji, ustawianej za pomocą
56 | funkcji \c gg_*_set_custom_resolver().
57 |
58 | */
59 |
--------------------------------------------------------------------------------
/examples/httphash.c:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2001-2006 Wojtek Kaniewski
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License Version
6 | * 2.1 as published by the Free Software Foundation.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU Lesser General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU Lesser General Public
14 | * License along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
16 | * USA.
17 | */
18 |
19 | #include
20 | #include
21 | #include
22 | #include "libgadu.h"
23 |
24 | int main(int argc, char **argv)
25 | {
26 | char buf[100];
27 | int i;
28 |
29 | if (argc > 2 && !strcmp(argv[1], "-b")) {
30 | int count = argc - 3;
31 | uint32_t val = atoi(argv[2]);
32 |
33 | for (i = 0; i < (1 << count); i++) {
34 | char *args[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
35 | uint32_t res;
36 | int c = 0, j;
37 |
38 | if (i & 1)
39 | args[c++] = argv[3];
40 | if (i & 2)
41 | args[c++] = argv[4];
42 | if (i & 4)
43 | args[c++] = argv[5];
44 | if (i & 8)
45 | args[c++] = argv[6];
46 | if (i & 16)
47 | args[c++] = argv[7];
48 | if (i & 32)
49 | args[c++] = argv[8];
50 | if (i & 64)
51 | args[c++] = argv[9];
52 | if (i & 128)
53 | args[c++] = argv[10];
54 |
55 | strcpy(buf, "");
56 |
57 | for (j = 0; j < c; j++)
58 | strcat(buf, "s");
59 |
60 | res = gg_http_hash(buf, args[0], args[1], args[2], args[3], args[4], args[5], args[6], NULL);
61 |
62 | printf("%s %s %s %s %s %s %s %s", buf, args[0], args[1],
63 | args[2], args[3], args[4], args[5], args[6]);
64 |
65 | if (res == val)
66 | printf(" MATCH!\n");
67 | else
68 | printf("\n");
69 | }
70 |
71 | return 0;
72 | }
73 |
74 | if (argc < 2 || argc > 10) {
75 | fprintf(stderr, "użycie: %s [wyrazy] [do] [hasha]\n", argv[0]);
76 | return 1;
77 | }
78 |
79 | strcpy(buf, "");
80 |
81 | for (i = 1; i < argc; i++)
82 | strcat(buf, "s");
83 |
84 | printf("%s\n", buf);
85 |
86 | printf("%u\n", gg_http_hash(buf, argv[1], argv[2], argv[3], argv[4],
87 | argv[5], argv[6], argv[7], argv[8], argv[9], argv[10]));
88 |
89 | return 0;
90 | }
91 |
--------------------------------------------------------------------------------
/include/protobuf.h:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2012 Tomek Wasilczyk
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License Version
6 | * 2.1 as published by the Free Software Foundation.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU Lesser General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU Lesser General Public
14 | * License along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
16 | * USA.
17 | */
18 |
19 | #include "internal.h"
20 |
21 | #ifndef LIBGADU_PROTOBUF_H
22 | #define LIBGADU_PROTOBUF_H
23 |
24 | #include
25 | #include
26 | #include
27 |
28 | #ifdef GG_CONFIG_HAVE_PROTOBUF_C
29 | #include
30 | #else
31 | #include "protobuf-c.h"
32 | #endif
33 |
34 | #include "fileio.h"
35 |
36 | typedef size_t (*gg_protobuf_size_cb_t)(const void *message);
37 | typedef size_t (*gg_protobuf_pack_cb_t)(const void *message, uint8_t *out);
38 |
39 | typedef struct _gg_protobuf_uin_buff gg_protobuf_uin_buff_t;
40 |
41 | /* Ostatni warunek (msg != NULL) jest tylko po to, żeby uciszyć analizę
42 | * statyczną (zawiera się w pierwszym). */
43 | #define GG_PROTOBUF_VALID(gs, name, msg) \
44 | (gg_protobuf_valid_chknull(gs, name, msg == NULL) && \
45 | gg_protobuf_valid_chkunknown(gs, name, &msg->base) && \
46 | msg != NULL)
47 |
48 | #define GG_PROTOBUF_SEND(gs, ge, packet_type, msg_type, msg) \
49 | gg_protobuf_send_ex(gs, ge, packet_type, &msg, \
50 | (gg_protobuf_size_cb_t) msg_type ## __get_packed_size, \
51 | (gg_protobuf_pack_cb_t) msg_type ## __pack)
52 |
53 | void gg_protobuf_expected(struct gg_session *gs, const char *field_name,
54 | uint32_t value, uint32_t expected);
55 |
56 | int gg_protobuf_valid_chknull(struct gg_session *gs, const char *msg_name,
57 | int isNull);
58 | int gg_protobuf_valid_chkunknown(struct gg_session *gs, const char *msg_name,
59 | ProtobufCMessage *base);
60 |
61 | int gg_protobuf_send_ex(struct gg_session *gs, struct gg_event *ge, int type,
62 | void *msg, gg_protobuf_size_cb_t size_cb,
63 | gg_protobuf_pack_cb_t pack_cb);
64 |
65 | void gg_protobuf_set_uin(ProtobufCBinaryData *dst, uin_t uin, gg_protobuf_uin_buff_t *buff);
66 | uin_t gg_protobuf_get_uin(ProtobufCBinaryData uin_data);
67 |
68 | #endif /* LIBGADU_PROTOBUF_H */
69 |
--------------------------------------------------------------------------------
/docs/mainpage.dox:
--------------------------------------------------------------------------------
1 | /**
2 |
3 | \mainpage libgadu
4 |
5 | \e libgadu jest biblioteką przeznaczoną do obsługi protokołu komunikatora
6 | Gadu-Gadu. Przez dłuższy czas była integralną częścią
7 | Eksperymentalnego Klienta Gadu-Gadu,
8 | lecz ze względu na problemy z dystrybucją pakietów i wykorzystaniem
9 | w innych projektach, została wydzielona. Własnościowy protokół został
10 | rozszyfrowany metodą \ref re "inżynierii wstecznej" (ang.
11 | \e "reverse engineering"), przez co \e libgadu może nie być w 100% zgodna
12 | z pierwowzorem.
13 |
14 | Należy pamiętać, że używanie alternatywnych klientów może być niezgodne
15 | z regulaminem korzystania z serwisu Gadu-Gadu.
16 |
17 | Biblioteka została napisana w języku C i jest niezależna od systemu
18 | operacyjnego czy środowiska. Pracuje pod systemami operacyjnymi zgodnymi
19 | z POSIX, również BeOS i Win32. Używana jest w aplikacjach konsolowych,
20 | jak i graficznych GTK+ i Qt.
21 |
22 | Biblioteka jest udostępniana na zasadach licencji LGPL w wersji 2.1,
23 | której treść znajduje się w pliku \c COPYING.
24 |
25 | Strona projektu znajduje się pod adresem https://libgadu.net/.
26 |
27 | Problemy z biblioteką można zgłaszać na stronie projektu w GitHubie pod
28 | adresem https://github.com/wojtekka/libgadu/issues. Używana wcześniej
29 | lista dyskusyjna libgadu-devel@lists.ziew.org nie jest już dostępna.
30 |
31 | Dokumentację podzielono na następujące działy:
32 |
33 | - Funkcje związane połączeniem
34 | - \ref login
35 | - \ref events
36 | - \ref contacts
37 | - \ref messages
38 | - \ref chat
39 | - \ref status
40 | - \ref pubdir50
41 | - \ref importexport
42 |
43 | - Funkcje związane z usługami dodatkowymi
44 | - \ref http
45 | - \ref token
46 | - \ref register
47 | - \ref passwd
48 | - \ref remind
49 | - \ref unregister
50 |
51 | - Funkcje związane z połączeniami bezpośrednimi
52 | - \ref dcc6
53 | - \ref dcc7
54 |
55 | - Pozostałe funkcje
56 | - \ref version
57 | - \ref proxy
58 | - \ref ip
59 | - \ref socketmanager
60 | - \ref debug
61 | - \ref helper
62 | - \ref todo
63 |
64 | - Informacje dodatkowe
65 | - \ref changelog
66 | - \ref re
67 | - \ref build
68 |
69 | \warning Należy pamiętać, że używanie alternatywnych klientów jest niezgodne
70 | z regulaminem korzystania z serwisu Gadu-Gadu.
71 |
72 | \note Na potrzeby przykładów użyto numerów kontaktów typu 1234 itp. Numery
73 | te prawdopodobnie są numerami używanymi, dlatego testując własny kod nie
74 | należy używać losowo wybranych numerów, tylko własnych lub
75 | zarejestrowanych na potrzeby testów. Dobrym zwyczajem jest również usuwanie
76 | kont po zakończeniu eksperymentów.
77 |
78 | \note
79 | */
80 |
--------------------------------------------------------------------------------
/examples/send.c:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2001-2006 Wojtek Kaniewski
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License Version
6 | * 2.1 as published by the Free Software Foundation.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU Lesser General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU Lesser General Public
14 | * License along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
16 | * USA.
17 | */
18 |
19 | /*
20 | * przykład prostego programu łączącego się z serwerem i wysyłającego
21 | * jedną wiadomość.
22 | */
23 |
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include "libgadu.h"
29 | #include "network.h"
30 |
31 | int main(int argc, char **argv)
32 | {
33 | struct gg_session *sess;
34 | struct gg_event *e;
35 | struct gg_login_params p;
36 |
37 | if (argc < 5) {
38 | fprintf(stderr, "użycie: %s \n", argv[0]);
39 | return 1;
40 | }
41 |
42 | #ifdef _WIN32
43 | gg_win32_init_network();
44 | #endif
45 |
46 | gg_debug_level = 255;
47 |
48 | memset(&p, 0, sizeof(p));
49 | p.uin = atoi(argv[2]);
50 | p.password = argv[1];
51 |
52 | if (!(sess = gg_login(&p))) {
53 | printf("Nie udało się połączyć: %s\n", strerror(errno));
54 | gg_free_session(sess);
55 | return 1;
56 | }
57 |
58 | printf("Połączono.\n");
59 |
60 | /* serwery gg nie pozwalaja wysylac wiadomosci bez powiadomienia
61 | * o userliscie (przetestowane p.protocol_version [0x15; def] */
62 | if (gg_notify(sess, NULL, 0) == -1) {
63 | printf("Połączenie przerwane: %s\n", strerror(errno));
64 | gg_free_session(sess);
65 | return 1;
66 | }
67 |
68 | if (gg_send_message(sess, GG_CLASS_MSG, atoi(argv[3]), (unsigned char*) argv[4]) == -1) {
69 | printf("Połączenie przerwane: %s\n", strerror(errno));
70 | gg_free_session(sess);
71 | return 1;
72 | }
73 |
74 | /* poniższą część można olać, ale poczekajmy na potwierdzenie */
75 |
76 | while (0) {
77 | if (!(e = gg_watch_fd(sess))) {
78 | printf("Połączenie przerwane: %s\n", strerror(errno));
79 | gg_logoff(sess);
80 | gg_free_session(sess);
81 | return 1;
82 | }
83 |
84 | if (e->type == GG_EVENT_ACK) {
85 | printf("Wysłano.\n");
86 | gg_free_event(e);
87 | break;
88 | }
89 |
90 | gg_free_event(e);
91 | }
92 |
93 | gg_logoff(sess);
94 | gg_free_session(sess);
95 |
96 | return 0;
97 | }
98 |
--------------------------------------------------------------------------------
/test/automatic/connect.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEowIBAAKCAQEAukPJMdEi8x738p90I50Dt59NBcYuzBH4zvD5LB3Cr4XQaPuc
3 | Xv01AriX4IGexVXbhsIV+VpXLRxClOrG+lSrV4clFsakILl3JxpPG7tItuVupzPg
4 | LExRYuTyfyYsqgPrjKMoOfTZEkG1kplJZB4sphT3tpFq3A2UykD8KD1IARuuZKlx
5 | QLj+dzYLJrVZYB/28b6Mz+EZv3+jLuRvkAMTTYcat/Gaos4CtkLXdVhRQ2Yg89gO
6 | LyhZ7jBAk8YhHXvu8rj1tGG1sjA8aFz8oVwZMLYCsX+Zh/qs0rdEF2JpIQi9HJEc
7 | 66Pk0PWVY+UF7dkiSqwJSg5AEsyJv5XkuntHbwIDAQABAoIBACBlv+3pSWHuJgRO
8 | Vb4IBmh+zb/OW79k9NjRsxVIS9+Jr9lCwk0HT5wcjVYgVYRPTbKfuYC4hOc0viP2
9 | vgs2hOLhf8L5Y/zJJX9opQ/WwGwHdfqhHEG4OIOx/Le+5Q/hRKweiNWjz8nMIg/Q
10 | l6JRWUS96uQXYPXLavDO4s0A87A1W2Y+umswwadb17+iBsn3xJpXwd3cjvrAS7q6
11 | r5ApjMvTrS+gDf2cAV1P4XCr8xnL6JjCP5Sh4LR5HmaFPHykOrU5o1qi+RBtK3M/
12 | J4mQ9Zt1nFtFttZVj+VXJYzJ7cVtTIfoniIrqjguM4LUaUU6ROhE8qhl6quMsQd6
13 | lmSkX0kCgYEA2Y9hWXXG8OFoZ+Aud9M0fHJjz5SCd/bRrFuJ8TwD0NbMkv9c2OLs
14 | q6Wb11iGxhaRCcdYPRP1EKwBk3f0SjHk/MLv8wK7ITb4ZQSHo5IuhSh5pZj12OXp
15 | dZxdASoZtIpVzTztGlLLOCO7eUhbHHiv+VZr3+mbXZ5Ve3yMRrBYrU0CgYEA2yzd
16 | iWkAc8RZCGqIQ5SLB9LpuattE3t8Hmsu9oy/B8W0BFtUYMhv1l95jQCaNkRHR/uW
17 | yKooiypKdbCuIYdjTpdxri2LdRNvF1Gg9T1APK7kfTxssHCPg9GxwrzJQ/nIVy0e
18 | KKsWPvMm7//IQN9roglAkUhcW4nhyT6IN3IfGasCgYEAobNFwb4eHQ8MEJi5MOpT
19 | ymMi+DgDOLLEaHyo7BmVJHViG6edFL6k9Xbje40arsQ7DK+TT+IzdS7DBR5U/YhU
20 | D+G7gjz3ZNp8iGhzgAm4ddP9hi1IHOvVN0r+fU0TSfK/jwnHmJcM4C7+ukgjH+g7
21 | svCewQ/aIBz8oAmUIT4UyskCgYAFp7uznvT3B7rwX6dSbxPDSOrk8opm9Um3kzZs
22 | ACexsKU7c4vSz3krQ91kCP7xpYNdVR2H4fQX2yh+rudfUBn83iV9xAkUJUM5i86m
23 | ZUUyC6Uzogp/5vedBB0dFDfxPBGyRiTAEeIKD8YSbTwiiGFDlg+HcCGJ7x3XTni/
24 | TX+F7wKBgDKPZAH1eFo7ot5JZ6VyBI3vggrBs7tG0VDHIOKjobvjGQi5aWVt9Fn1
25 | ht85SQQOhtP3J+EfBuSkI8TVPbFq4ah5D7Fv1jpAcLnSlk3tOMY7/4yc+1bvpj4F
26 | lQhTaJz3WdCNcAN7qSNVBm9QI+JAS/HlTMowGrxHib+ycG20GoB3
27 | -----END RSA PRIVATE KEY-----
28 | -----BEGIN CERTIFICATE-----
29 | MIIDETCCAfugAwIBAgIETh9XIDALBgkqhkiG9w0BAQUwNTELMAkGA1UEBhMCUEwx
30 | FDASBgNVBAoTC3RveHlnZW4ubmV0MRAwDgYDVQQDEwdsaWJnYWR1MB4XDTExMDcx
31 | NDIwNTI1MloXDTE4MTAwNTA3NTYzMFowNTELMAkGA1UEBhMCUEwxFDASBgNVBAoT
32 | C3RveHlnZW4ubmV0MRAwDgYDVQQDEwdsaWJnYWR1MIIBIDALBgkqhkiG9w0BAQED
33 | ggEPADCCAQoCggEBALpDyTHRIvMe9/KfdCOdA7efTQXGLswR+M7w+Swdwq+F0Gj7
34 | nF79NQK4l+CBnsVV24bCFflaVy0cQpTqxvpUq1eHJRbGpCC5dycaTxu7SLblbqcz
35 | 4CxMUWLk8n8mLKoD64yjKDn02RJBtZKZSWQeLKYU97aRatwNlMpA/Cg9SAEbrmSp
36 | cUC4/nc2Cya1WWAf9vG+jM/hGb9/oy7kb5ADE02HGrfxmqLOArZC13VYUUNmIPPY
37 | Di8oWe4wQJPGIR177vK49bRhtbIwPGhc/KFcGTC2ArF/mYf6rNK3RBdiaSEIvRyR
38 | HOuj5ND1lWPlBe3ZIkqsCUoOQBLMib+V5Lp7R28CAwEAAaMvMC0wDAYDVR0TAQH/
39 | BAIwADAdBgNVHQ4EFgQUikoo/PrQPvmxY9lw+2Axg/CIbRMwCwYJKoZIhvcNAQEF
40 | A4IBAQC3IgTw74B7D1VikYrg2cQAfk+GHEiDZZrljI+gvkf4OWjzQK8JzmBHnLLH
41 | z7lj6CgAxFwuIIjt83nKt6kyaaQ5mTMUEOkPp/qK19RMAeiSc/kqY+Z3u7mZlUOy
42 | VRkRPZotxpzLBZWyf9j397f3xsCQj/sW20DJjHb/t8xviHgNKYw9ANVPIF3uuUjP
43 | yy3bx64qcoetIdadyZOKAoTbQ7WuqC4Gc6uVRWxcO4x5tzn7zE3YfwwnVE3ENYox
44 | JnXIE6zuKWwiDS4sBgRdSZ6qbAh5N+seCw9rFtzVk5OZy24QQVcmUErjAIHCXGNp
45 | U4PlXLrYZOq/uKlopi6m+BDGhic5
46 | -----END CERTIFICATE-----
47 |
--------------------------------------------------------------------------------
/test/manual/userconfig.c:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2001-2006 Wojtek Kaniewski
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License Version
6 | * 2.1 as published by the Free Software Foundation.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU Lesser General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU Lesser General Public
14 | * License along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
16 | * USA.
17 | */
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 |
24 | #include "libgadu.h"
25 | #include "network.h"
26 | #include "userconfig.h"
27 |
28 | unsigned int config_uin;
29 | char *config_password;
30 | unsigned int config_peer;
31 | char *config_file;
32 | char *config_dir;
33 | unsigned int config_size = 1048576;
34 | unsigned long config_ip = 0xffffffff;
35 | unsigned int config_port;
36 | char *config_server;
37 | char *config_proxy;
38 |
39 | int config_read(void)
40 | {
41 | char buf[256];
42 | FILE *f;
43 |
44 | if (!(f = fopen("config", "r"))) {
45 | if (!(f = fopen("../config", "r")))
46 | return -1;
47 | }
48 |
49 | while (fgets(buf, sizeof(buf), f)) {
50 | while (strlen(buf) > 0 && isspace(buf[strlen(buf) - 1]))
51 | buf[strlen(buf) - 1] = 0;
52 |
53 | if (strncmp(buf, "uin ", 4) == 0)
54 | config_uin = atoi(buf + 4);
55 |
56 | if (strncmp(buf, "password ", 9) == 0) {
57 | free(config_password);
58 | config_password = strdup(buf + 9);
59 | }
60 |
61 | if (strncmp(buf, "peer ", 5) == 0)
62 | config_peer = atoi(buf + 5);
63 |
64 | if (strncmp(buf, "file ", 5) == 0) {
65 | free(config_file);
66 | config_file = strdup(buf + 5);
67 | }
68 |
69 | if (strncmp(buf, "dir ", 4) == 0) {
70 | free(config_dir);
71 | config_dir = strdup(buf + 4);
72 | }
73 |
74 | if (strncmp(buf, "size ", 5) == 0)
75 | config_size = atoi(buf + 5);
76 |
77 | if (strncmp(buf, "ip ", 3) == 0)
78 | config_ip = inet_addr(buf + 3);
79 |
80 | if (strncmp(buf, "port ", 5) == 0)
81 | config_port = atoi(buf + 5);
82 |
83 | if (strncmp(buf, "server ", 7) == 0) {
84 | free(config_server);
85 | config_server = strdup(buf + 7);
86 | }
87 |
88 | if (strncmp(buf, "proxy ", 6) == 0) {
89 | free(config_proxy);
90 | config_proxy = strdup(buf + 6);
91 | }
92 | }
93 |
94 | fclose(f);
95 |
96 | if (config_uin == 0 || config_password == NULL)
97 | return -1;
98 |
99 | return 0;
100 | }
101 |
102 | void config_free(void)
103 | {
104 | free(config_password);
105 | free(config_dir);
106 | free(config_file);
107 | free(config_server);
108 | free(config_proxy);
109 | }
110 |
--------------------------------------------------------------------------------
/README.en:
--------------------------------------------------------------------------------
1 | libgadu 1.12.3-pre
2 | (C) Copyright 2001-2019 Authors (full list in AUTHORS file)
3 |
4 | libgadu is a library for handling Gadu-Gadu instant messenger protocol.
5 | For a long time it was an intergral part of ekg application but due to
6 | packaging issues and use in other appliactions it became a project on its
7 | own. Proprietary protocol was reverse engineered which may make libgadu less
8 | than 100% compatible with the original. It's important to note that the use
9 | of unofficial clients may be forbidden by terms and conditions of Gadu-Gadu.
10 |
11 | It's important to note that the use of unofficial clients may be forbidden
12 | by the terms and conditions of Gadu-Gadu.
13 |
14 | The library is written in C and aims to be operating system and environment
15 | independent. It works in POSIX-compliant operating systems, also BeOS and
16 | Win32 although the latter is not supported because of an official Gadu-Gadu
17 | client for that platform. It's used in terminal applications as well as GTK+
18 | and Qt ones.
19 |
20 | The library is released on the terms of LGPL 2.1 license which can be found
21 | in COPYING file.
22 |
23 | Project website is available at https://libgadu.net/.
24 |
25 | Problems with the library can be reported at project's GitHub page at
26 | https://github.com/wojtekka/libgadu/issues. Previously used mailing list
27 | libgadu-devel@lists.ziew.org is no longer available.
28 |
29 | Requirements
30 | ------------
31 |
32 | Encrypted connections require either GnuTLS or OpenSSL. The latter is not
33 | used by default even if it's available - software linked with this library
34 | is incompatible with GPL which causes issues with use of libgadu in
35 | GPL-licensed software. To use it anyway one needs to use --with-openssl
36 | parameter. The library built in such way will be only partially
37 | binary-compatible with a default version and gg_is_gpl_compliant symbol
38 | will be missing. Software wanting to make sure that libgadu is GPL-compliant
39 | may reference this symbol. Mininum version of OpenSSL is 0.9.7 and GnuTLS is
40 | 2.10.0. When using OpenSSL or GnuTLS below 3.0 the certificate revocation
41 | is not supported.
42 |
43 | To store contact list on the server zlib library is required.
44 |
45 | Documentation is generated using Doxygen. It's optional.
46 |
47 | Some unit tests require glibc, GnuTLS, libxml2 and Perl. If these are not
48 | available some tests will not be run. Furthermore some manual test programs
49 | use CURL, Expat and OpenSSL.
50 |
51 | The compiler must support 64-bit long long type.
52 |
53 | During compilation a version of standard library is detected because the
54 | behavior of printf() family of function changed in ISO C99. This is
55 | impossible during crosscompilation so the use of --with- or
56 | --without-c99-vsnprintf parameter is necessary. Most of modern operating
57 | systems provide C99-compliant standard library so in case of doubt one
58 | can use --with-c99-vsnprintf.
59 |
60 | An asynchronous domain name resolver uses processes or pthreads. If the
61 | system library provides gethostbyname_r() function for use in multithreaded
62 | applications (Linux with glibc, SunOS) it will be used.
63 |
64 |
--------------------------------------------------------------------------------
/test/automatic/script/05-multilogon.scr:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------------
2 | # Multilogon disconnect
3 | #-----------------------------------------------------------------------------
4 | call {
5 | gg_multilogon_id_t id;
6 |
7 | memcpy(&id, "\x11\x22\x33\x44\x55\x66\x77\x88", 8);
8 |
9 | gg_multilogon_disconnect(session, id);
10 | }
11 |
12 | expect data (62 00 00 00, auto, 11 22 33 44 55 66 77 88)
13 |
14 | #-----------------------------------------------------------------------------
15 | # Multilogon data
16 | #-----------------------------------------------------------------------------
17 |
18 | send (5b 00 00 00, auto, 00 00 00 00)
19 |
20 | expect event GG_EVENT_MULTILOGON_INFO (
21 | multilogon_info.count == 0
22 | )
23 |
24 | send (5b 00 00 00, auto, 01 00 00 00, 7f 00 00 01, 67 45 23 01, 78 56 34 12, 89 67 45 23, 12 23 34 45 56 67 78 89, 00 00 00 00, 04 00 00 00, "Test", "some_additional_data")
25 |
26 | expect event GG_EVENT_MULTILOGON_INFO (
27 | multilogon_info.count == 1
28 | multilogon_info.sessions[0].remote_addr == 127.0.0.1
29 | multilogon_info.sessions[0].status_flags == 0x01234567
30 | multilogon_info.sessions[0].protocol_features == 0x12345678
31 | multilogon_info.sessions[0].logon_time == 0x23456789
32 | multilogon_info.sessions[0].name == "Test"
33 | )
34 |
35 | send (5b 00 00 00, auto, 02 00 00 00, 7f 00 00 01, 67 45 23 01, 78 56 34 12, 89 67 45 23, 12 23 34 45 56 67 78 89, 00 00 00 00, 05 00 00 00, "First", 7f 00 00 02, 10 32 54 76, 21 43 65 87, 32 54 76 98, 98 87 76 65 54 43 32 21, 00 00 00 00, 06 00 00 00, "Second")
36 |
37 | expect event GG_EVENT_MULTILOGON_INFO (
38 | multilogon_info.count == 2
39 | multilogon_info.sessions[0].remote_addr == 127.0.0.1
40 | multilogon_info.sessions[0].status_flags == 0x01234567
41 | multilogon_info.sessions[0].protocol_features == 0x12345678
42 | multilogon_info.sessions[0].logon_time == 0x23456789
43 | multilogon_info.sessions[0].name == "First"
44 | multilogon_info.sessions[1].remote_addr == 127.0.0.2
45 | multilogon_info.sessions[1].status_flags == 0x76543210
46 | multilogon_info.sessions[1].protocol_features == (int)0x87654321
47 | multilogon_info.sessions[1].logon_time == (logon_time_t)0x98765432
48 | multilogon_info.sessions[1].name == "Second"
49 | )
50 |
51 | #-----------------------------------------------------------------------------
52 | # Malformed data
53 | #-----------------------------------------------------------------------------
54 |
55 | send (5b 00 00 00, auto, 00 00 00)
56 |
57 | expect event GG_EVENT_NONE
58 |
59 | send (5b 00 00 00, auto, ff ff ff ff)
60 |
61 | expect event GG_EVENT_NONE
62 |
63 | send (5b 00 00 00, auto, 01 00 00 00, 11 22 33 44, 55 66 77 88, 99 aa bb cc, dd, ee, ff, 00, 11 22 33 44 55 66 77 88, 99 aa bb cc, dd ee ff)
64 |
65 | expect event GG_EVENT_NONE
66 |
67 | send (5b 00 00 00, auto, 01 00 00 00, 11 22 33 44, 55 66 77 88, 99 aa bb cc, dd, ee, ff, 00, 11 22 33 44 55 66 77 88, 99 aa bb cc, 01 00 00 00)
68 |
69 | expect event GG_EVENT_NONE
70 |
71 | send (5b 00 00 00, auto, 01 00 00 00, 11 22 33 44, 55 66 77 88, 99 aa bb cc, dd, ee, ff, 00, 11 22 33 44 55 66 77 88, 99 aa bb cc, ff ff ff ff)
72 |
73 | expect event GG_EVENT_NONE
74 |
75 |
76 |
--------------------------------------------------------------------------------
/examples/register.c:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2001-2006 Wojtek Kaniewski
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License Version
6 | * 2.1 as published by the Free Software Foundation.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU Lesser General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU Lesser General Public
14 | * License along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
16 | * USA.
17 | */
18 |
19 | #include
20 | #include
21 | #include "libgadu.h"
22 |
23 | #ifdef ASYNC
24 |
25 | #ifdef _WIN32
26 | # include
27 | #else
28 | # include
29 | # include
30 | #endif
31 | #include
32 | #include
33 |
34 | #ifndef _WIN32
35 | static void sigchld(int sig)
36 | {
37 | wait(NULL);
38 | signal(SIGCHLD, sigchld);
39 | }
40 | #endif
41 |
42 | #endif
43 |
44 | int main(int argc, char **argv)
45 | {
46 | struct gg_http *h;
47 | struct gg_pubdir *p;
48 | const char *email;
49 | const char *password;
50 | const char *tokenid;
51 | const char *tokenval;
52 |
53 | if (argc < 5) {
54 | printf("Użycie: %s \n", argv[0]);
55 | return 1;
56 | }
57 |
58 | email = argv[1];
59 | password = argv[2];
60 | tokenid = argv[3];
61 | tokenval = argv[4];
62 |
63 | gg_debug_level = 255;
64 |
65 | #ifndef ASYNC
66 | if (!(h = gg_register3(email, password, tokenid, tokenval, 0))) {
67 | printf("Błąd rejestracji.\n");
68 | return 1;
69 | }
70 |
71 | #else
72 |
73 | #ifndef _WIN32
74 | signal(SIGCHLD, sigchld);
75 | #endif
76 |
77 | if (!(h = gg_register3(email, password, tokenid, tokenval, 1)))
78 | return 1;
79 |
80 | while (1) {
81 | fd_set rd, wr, ex;
82 |
83 | FD_ZERO(&rd);
84 | FD_ZERO(&wr);
85 | FD_ZERO(&ex);
86 |
87 | if ((h->check & GG_CHECK_READ))
88 | FD_SET(h->fd, &rd);
89 | if ((h->check & GG_CHECK_WRITE))
90 | FD_SET(h->fd, &wr);
91 | FD_SET(h->fd, &ex);
92 |
93 | if (select(h->fd + 1, &rd, &wr, &ex, NULL) == -1 || FD_ISSET(h->fd, &ex)) {
94 | if (errno == EINTR)
95 | continue;
96 | gg_free_register(h);
97 | perror("select");
98 | return 1;
99 | }
100 |
101 | if (FD_ISSET(h->fd, &rd) || FD_ISSET(h->fd, &wr)) {
102 | if (gg_register_watch_fd(h) == -1) {
103 | gg_free_register(h);
104 | fprintf(stderr, "Błąd połączenia.\n");
105 | return 1;
106 | }
107 | if (h->state == GG_STATE_ERROR) {
108 | gg_free_register(h);
109 | fprintf(stderr, "Błąd rejestracji.\n");
110 | return 1;
111 | }
112 | if (h->state == GG_STATE_DONE)
113 | break;
114 | }
115 | }
116 | #endif
117 |
118 | p = h->data;
119 | printf("success=%d\nuin=%d\n", p->success, p->uin);
120 | gg_free_register(h);
121 |
122 | return 0;
123 | }
124 |
--------------------------------------------------------------------------------
/examples/remind.c:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2001-2006 Wojtek Kaniewski
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License Version
6 | * 2.1 as published by the Free Software Foundation.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU Lesser General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU Lesser General Public
14 | * License along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
16 | * USA.
17 | */
18 |
19 | #include
20 | #include
21 | #include "libgadu.h"
22 |
23 | #ifdef ASYNC
24 |
25 | #ifdef _WIN32
26 | # include
27 | #else
28 | # include
29 | # include
30 | #endif
31 | #include
32 | #include
33 |
34 | #ifndef _WIN32
35 | static void sigchld(int sig)
36 | {
37 | wait(NULL);
38 | signal(SIGCHLD, sigchld);
39 | }
40 | #endif
41 |
42 | #endif
43 |
44 | int main(int argc, char **argv)
45 | {
46 | struct gg_http *h;
47 | struct gg_pubdir *p;
48 | uin_t uin;
49 | const char *email;
50 | const char *tokenid;
51 | const char *tokenval;
52 |
53 | if (argc < 5) {
54 | printf("Użycie: %s \n", argv[0]);
55 | return 1;
56 | }
57 |
58 | uin = atoi(argv[1]);
59 | email = argv[2];
60 | tokenid = argv[3];
61 | tokenval = argv[4];
62 |
63 | gg_debug_level = 255;
64 |
65 | #ifndef ASYNC
66 | if (!(h = gg_remind_passwd3(uin, email, tokenid, tokenval, 0))) {
67 | printf("Błąd przypominania hasła.\n");
68 | return 1;
69 | }
70 | #else
71 |
72 | #ifndef _WIN32
73 | signal(SIGCHLD, sigchld);
74 | #endif
75 |
76 | if (!(h = gg_remind_passwd3(uin, email, tokenid, tokenval, 1)))
77 | return 1;
78 |
79 | while (1) {
80 | fd_set rd, wr, ex;
81 |
82 | FD_ZERO(&rd);
83 | FD_ZERO(&wr);
84 | FD_ZERO(&ex);
85 |
86 | if ((h->check & GG_CHECK_READ))
87 | FD_SET(h->fd, &rd);
88 | if ((h->check & GG_CHECK_WRITE))
89 | FD_SET(h->fd, &wr);
90 | FD_SET(h->fd, &ex);
91 |
92 | if (select(h->fd + 1, &rd, &wr, &ex, NULL) == -1 || FD_ISSET(h->fd, &ex)) {
93 | if (errno == EINTR)
94 | continue;
95 | gg_free_remind_passwd(h);
96 | perror("select");
97 | return 1;
98 | }
99 |
100 | if (FD_ISSET(h->fd, &rd) || FD_ISSET(h->fd, &wr)) {
101 | if (gg_remind_passwd_watch_fd(h) == -1) {
102 | gg_free_remind_passwd(h);
103 | fprintf(stderr, "Błąd połączenia.\n");
104 | return 1;
105 | }
106 | if (h->state == GG_STATE_ERROR) {
107 | gg_free_remind_passwd(h);
108 | fprintf(stderr, "Błąd przypominania hasła.\n");
109 | return 1;
110 | }
111 | if (h->state == GG_STATE_DONE)
112 | break;
113 | }
114 | }
115 | #endif
116 |
117 | p = h->data;
118 | printf("success=%d\n", p->success);
119 | gg_free_remind_passwd(h);
120 |
121 | return 0;
122 | }
123 |
--------------------------------------------------------------------------------
/test/manual/lib/http.c:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2008 Wojtek Kaniewski
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License Version
6 | * 2.1 as published by the Free Software Foundation.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU Lesser General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU Lesser General Public
14 | * License along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
16 | * USA.
17 | */
18 |
19 | #include
20 | #include
21 | #include
22 |
23 | #include "http.h"
24 |
25 | static size_t handle_data(void *ptr, size_t size, size_t nmemb, void *stream)
26 | {
27 | char *new_text, **text_ptr;
28 | size_t bytes, text_len;
29 |
30 | text_ptr = (char**) stream;
31 |
32 | bytes = size * nmemb;
33 |
34 | #if 0
35 | printf("Read %d\n", bytes);
36 | #endif
37 |
38 | if (*text_ptr == NULL) {
39 | text_len = 0;
40 | new_text = malloc(bytes + 1);
41 | } else {
42 | text_len = strlen(*text_ptr);
43 | new_text = realloc(*text_ptr, text_len + bytes + 1);
44 | }
45 |
46 | if (new_text == NULL) {
47 | free(*text_ptr);
48 | *text_ptr = NULL;
49 | return 0;
50 | }
51 |
52 | memcpy(new_text + text_len, ptr, bytes);
53 | new_text[text_len + bytes] = 0;
54 | *text_ptr = new_text;
55 |
56 | return bytes;
57 | }
58 |
59 | char *gg_http_fetch(const char *method, const char *url, const char *auth_header, char *post_data)
60 | {
61 | CURL *c;
62 | struct curl_slist *hdr = NULL;
63 | char *text = NULL;
64 | char **write_data_to = &text;
65 |
66 | c = curl_easy_init();
67 |
68 | if (c == NULL)
69 | return NULL;
70 |
71 | if (auth_header)
72 | hdr = curl_slist_append(hdr, auth_header);
73 |
74 | curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, handle_data);
75 | curl_easy_setopt(c, CURLOPT_WRITEDATA, write_data_to);
76 | curl_easy_setopt(c, CURLOPT_USERAGENT, "Gadu-Gadu Client, build 8,0,0,4881");
77 | curl_easy_setopt(c, CURLOPT_URL, url);
78 | curl_easy_setopt(c, CURLOPT_HTTPHEADER, hdr);
79 | if (strcmp(method, "POST") == 0) {
80 | curl_easy_setopt(c, CURLOPT_HTTPPOST, NULL);
81 | if (post_data)
82 | curl_easy_setopt(c, CURLOPT_POSTFIELDS, post_data);
83 | }
84 | /* from gadu-gadu, under LGPL 3.0 :> */
85 | curl_easy_setopt(c, CURLOPT_FOLLOWLOCATION, 0); /* bylo 1 */
86 | /* curl_easy_setopt(c, CURLOPT_RETURNTRANSFER, 1); */
87 | curl_easy_setopt(c, CURLOPT_SSL_VERIFYPEER, 0);
88 | curl_easy_setopt(c, CURLOPT_SSL_VERIFYHOST, 0);
89 | curl_easy_setopt(c, CURLOPT_MAXREDIRS, 3);
90 |
91 | #if 0
92 | curl_easy_setopt(c, CURLOPT_VERBOSE, 1);
93 | #endif
94 |
95 | curl_easy_perform(c);
96 |
97 | if (hdr)
98 | curl_slist_free_all(hdr);
99 |
100 | curl_easy_cleanup(c);
101 |
102 | return text;
103 | }
104 |
105 | void http_init(void)
106 | {
107 | curl_global_init(CURL_GLOBAL_SSL);
108 | }
109 |
--------------------------------------------------------------------------------
/examples/conn-async.c:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2001-2006 Wojtek Kaniewski
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License Version
6 | * 2.1 as published by the Free Software Foundation.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU Lesser General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU Lesser General Public
14 | * License along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
16 | * USA.
17 | */
18 |
19 | /*
20 | * Przykładowy program demonstrujący asynchroniczne połączenie z serwerem.
21 | * Poza połączeniem nie robi nic. Nie przejmuje się błędami.
22 | */
23 |
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include "libgadu.h"
31 | #include "network.h"
32 |
33 | int main(void)
34 | {
35 | struct gg_login_params p;
36 | struct gg_session *sess;
37 | struct timeval tv;
38 | struct gg_event *e;
39 | fd_set rd, wd;
40 | time_t last = 0, now;
41 | int ret;
42 |
43 | #ifdef _WIN32
44 | gg_win32_init_network();
45 | #endif
46 |
47 | gg_debug_level = ~0;
48 |
49 | memset(&p, 0, sizeof(p));
50 | p.uin = 123456;
51 | p.password = "qwerty";
52 | p.async = 1;
53 |
54 | sess = gg_login(&p);
55 |
56 | if (!sess) {
57 | printf("gg_login failed.\n");
58 | return 1;
59 | }
60 |
61 | for (;;) {
62 | FD_ZERO(&rd);
63 | FD_ZERO(&wd);
64 |
65 | if ((sess->check & GG_CHECK_READ))
66 | FD_SET(sess->fd, &rd);
67 | if ((sess->check & GG_CHECK_WRITE))
68 | FD_SET(sess->fd, &wd);
69 |
70 | tv.tv_sec = 1;
71 | tv.tv_usec = 0;
72 |
73 | ret = select(sess->fd + 1, &rd, &wd, NULL, &tv);
74 |
75 | if (ret == -1) {
76 | perror("select");
77 | return 1;
78 | }
79 |
80 | now = time(NULL);
81 |
82 | if (now != last) {
83 | if (sess->timeout != -1 && sess->timeout-- == 0 &&
84 | !sess->soft_timeout)
85 | {
86 | printf("Przekroczenie czasu operacji.\n");
87 | gg_free_session(sess);
88 | return 1;
89 | }
90 | }
91 |
92 | if (sess && (FD_ISSET(sess->fd, &rd) ||
93 | FD_ISSET(sess->fd, &wd) ||
94 | (sess->timeout == 0 && sess->soft_timeout)))
95 | {
96 | if (!(e = gg_watch_fd(sess))) {
97 | printf("Połączenie zerwane.\n");
98 | gg_free_session(sess);
99 | return 1;
100 | }
101 |
102 | if (e->type == GG_EVENT_CONN_SUCCESS) {
103 | printf("Połączono z serwerem.\n");
104 | gg_free_event(e);
105 | gg_logoff(sess);
106 | gg_free_session(sess);
107 | return 0;
108 | }
109 |
110 | if (e->type == GG_EVENT_CONN_FAILED) {
111 | printf("Błąd połączenia.\n");
112 | gg_free_event(e);
113 | gg_logoff(sess);
114 | gg_free_session(sess);
115 | return 1;
116 | }
117 |
118 | gg_free_event(e);
119 | }
120 | }
121 |
122 | return 1;
123 | }
124 |
--------------------------------------------------------------------------------
/test/automatic/script/00-login.scr:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------------
2 | # Successful login
3 | #-----------------------------------------------------------------------------
4 | login (uin = 1, password = "")
5 | expect connect
6 | send (01 00 00 00, auto, 12 34 56 78)
7 | expect data (83 00 00 00, auto, xx*266)
8 | send (03 00 00 00, auto)
9 | expect event GG_EVENT_CONN_SUCCESS
10 | logoff
11 | expect disconnect
12 |
13 | #-----------------------------------------------------------------------------
14 | # Successful login with missing e-mail
15 | #-----------------------------------------------------------------------------
16 |
17 | login (uin = 1, password = "")
18 | expect connect
19 | send (01 00 00 00, auto, 12 34 56 78)
20 | expect data (83 00 00 00, auto, xx*266)
21 | send (14 00 00 00, auto)
22 | expect event GG_EVENT_CONN_SUCCESS
23 | logoff
24 | expect disconnect
25 |
26 | #-----------------------------------------------------------------------------
27 | # Failed login
28 | #-----------------------------------------------------------------------------
29 |
30 | login (uin = 1, password = "")
31 | expect connect
32 | send (01 00 00 00, auto, 12 34 56 78)
33 | expect data (83 00 00 00, auto, xx*266)
34 | send (09 00 00 00, auto)
35 | expect event GG_EVENT_CONN_FAILED
36 | logoff
37 | expect disconnect
38 |
39 | #-----------------------------------------------------------------------------
40 | # Login with parameters
41 | #-----------------------------------------------------------------------------
42 | login (uin = 0x123456, password = "ABC", status = GG_STATUS_INVISIBLE_DESCR, status_descr = "Test", has_audio = 1, image_size = 255, external_addr = 127.0.0.1, external_port = 0x1234, status_flags = 0x11223344, client_version = "1.2.3.4")
43 | expect connect
44 | send (01 00 00 00, auto, 12 34 56 78)
45 | expect data (83 00 00 00, auto, 0a 02 "pl", 12 09 01 07 "1193046", 1a 14 xx*20, 20 04, 2d 77 ff ee 03, 35 14 06 03 00, 3a 61 "GG-Phoenix/1.2.3.4 (BUILD;WINNT_x86-msvc;rv:11.0,pl;release;standard) (OS;Windows;Windows NT 6.1)", 45 16 00 00 00, 4a 04 "Test", 52 04 00 00 00 00, 5a 58 "avatar,StatusComments,ggaccount,edisc,music_shared,bot,fanpage,pubdir,botCaps,gifts,Gift", 60 ff 01, 68 64, 75 7f 00 00 00, 78 00, 88 01 00)
46 | send (03 00 00 00, auto)
47 | expect event GG_EVENT_CONN_SUCCESS
48 | logoff
49 | expect disconnect
50 |
51 | #-----------------------------------------------------------------------------
52 | # Login with custom client_version
53 | #-----------------------------------------------------------------------------
54 | login (uin = 1, password = "", client_version = "Foobar 1.2.3.4")
55 | expect connect
56 | send (01 00 00 00, auto, 12 34 56 78)
57 | expect data (83 00 00 00, auto, xx*43, 3a 0e "Foobar 1.2.3.4", xx*118)
58 | send (03 00 00 00, auto)
59 | expect event GG_EVENT_CONN_SUCCESS
60 | logoff
61 | expect disconnect
62 |
63 | #-----------------------------------------------------------------------------
64 | # Simple login before further tests
65 | #-----------------------------------------------------------------------------
66 | login (uin = 0x123456, password = "", encoding = GG_ENCODING_UTF8)
67 | expect connect
68 | send (01 00 00 00, auto, 12 34 56 78)
69 | expect data (83 00 00 00, auto, xx*272)
70 | send (03 00 00 00, auto)
71 | expect event GG_EVENT_CONN_SUCCESS
72 |
73 |
--------------------------------------------------------------------------------
/docs/dcc7.dox:
--------------------------------------------------------------------------------
1 | /**
2 |
3 | \defgroup dcc7 Połączenia bezpośrednie od wersji Gadu-Gadu 7.x
4 | \ingroup dcc
5 |
6 | \details
7 |
8 | Przesyłanie plików zgodne z Gadu-Gadu 7.x jest znacznie prostsze niż
9 | w wersji \ref dcc6 "6.x". Podobnie jak poprzednio, każde połączenie jest
10 | opisane przez strukturę \c gg_dcc7. Nie ma konieczności otwierania gniazda
11 | nasłuchującego, ponieważ jest tworzone dla każdego połączenia osobno.
12 |
13 | Gdy chcemy wysłać plik, wywołujemy \c gg_dcc7_send_file() i obserwujemy
14 | zdarzenia zarówno z \c gg_session, jak i \c gg_dcc7. Parametry funkcji
15 | to struktura sesji, numer odbiorcy, nazwa pliku, nazwa pliku w kodowaniu
16 | CP1250 (jeśli NULL to brana jest oryginalna nazwa) i skrót pliku
17 | wyznaczony algorytmem SHA1 (jeśli NULL to biblioteka liczy, blokując
18 | na ten czas działanie aplikacji). Wysyłanie jest praktycznie bezobsługowe,
19 | wystarczy zareagować na zdarzenie \c GG_EVENT_DCC7_DONE i
20 | \c GG_EVENT_DCC7_ERROR w gg_dcc7 oraz \c GG_EVENT_DCC7_REJECTED i
21 | \c GG_EVENT_DCC7_ERROR w \c gg_session, żeby wiedzieć, kiedy zwolnić zasoby
22 | funkcją \c gg_dcc7_free().
23 |
24 | Jeśli ktoś do nas wysyła plik, otrzymamy zdarzenie \c GG_EVENT_DCC7_NEW
25 | z sesji. Należy przygotować deskryptor otwarty do zapisu, wpisać jego
26 | wartość do pola \c file_fd struktury \c gg_dcc7 i wywołać \c gg_dcc7_accept()
27 | albo od razu wywołać \c gg_dcc7_reject(), jeśli nie chcemy połączenia. Tak samo
28 | jak przy wysyłaniu, wystarczy obsłużyć \c GG_EVENT_DCC7_DONE w strukturze
29 | \c gg_dcc7 i \c GG_EVENT_DCC7_ERROR w strukturach \c gg_session i \c gg_dcc7.
30 |
31 | Deskryptor połączenia (pole \c fd struktury \c gg_dcc7) może zmienić się
32 | po wywołaniu funkcji \c gg_dcc7_accept() lub otrzymaniu jednego ze zdarzeń:
33 | \c GG_EVENT_DCC7_CONNECTED, \c GG_EVENT_DCC7_ACCEPT, \c GG_EVENT_DCC7_PENDING.
34 |
35 | \section dcc7-settings Opcje połączeń
36 |
37 | Ponieważ jedna ze stron odbiera połączenie bezpośrednie, konieczne jest
38 | nasłuchiwanie na porcie TCP. Domyślne ustawienia pozwalają na poprawną
39 | pracę jeśli co najmniej jedna ze stron połączenia ma bezpośredni dostęp
40 | do sieci, bez translacji adresów i/lub portów. Pole
41 | \ref gg_login_params::client_addr "\c client_addr"
42 | struktury \c gg_login_params
43 | mówi na jakim adresie należy nasłuchiwać. Domyślna wartość \c 0.0.0.0 powoduje
44 | nasłuchiwanie na wszystkich dostępnych interfejsach komputera. Pole
45 | \ref gg_login_params::client_port "\c client_port"
46 | mówi na którym porcie
47 | należy nasłuchiwać. Domyślna wartość \c 0 powoduje nasłuchiwanie na losowym
48 | dostępnym porcie. Należy zwrócić uwagę, że jeśli jedno połączenie będzie
49 | nasłuchiwać na danym porcie, inne już nie będzie w stanie, co spowoduje błąd.
50 |
51 | Druga para ustawień dotyczy publicznego adresu i portu. Ta strona połączenia,
52 | która nasłuchuje na porcie TCP wysyła do drugiej strony swój adres i numer
53 | portu. Pole \ref gg_login_params::external_addr "\c external_addr"
54 | mówi jaki adres zostanie wysłany. Domyślna wartość \c 0.0.0.0 powoduje
55 | wysłanie adresu IP, z którego sesja łączy się z serwerem. Pole
56 | \ref gg_login_params::external_port "\c external_port"
57 | mówi jaki port zostanie wysłany. Domyślna wartość \c 0 powoduje wysłane portu,
58 | na którym połączenie nasłuchuje.
59 |
60 | \section dcc7-todo Do zrobienia
61 |
62 | - Rozmowy głosowe.
63 |
64 | - Nawiązywanie połączeń przez serwer.
65 |
66 | */
67 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | libgadu 1.12.3-pre
2 | (C) Copyright 2001-2019 Autorzy (pełna lista w pliku AUTHORS)
3 |
4 | libgadu jest biblioteką przeznaczoną do obsługi protokołu komunikatora
5 | Gadu-Gadu. Przez dłuższy czas była integralną częścią Eksperymentalnego
6 | Klienta Gadu-Gadu, lecz ze względu na problemy z dystrybucją pakietów
7 | i wykorzystaniem w innych projektach, została wydzielona. Własnościowy
8 | protokół został rozszyfrowany metodą inżynierii wstecznej (ang. "reverse
9 | engineering"), przez co libgadu może nie być w 100% zgodna
10 | z pierwowzorem.
11 |
12 | Należy pamiętać, że używanie alternatywnych klientów może być niezgodne
13 | z regulaminem korzystania z serwisu Gadu-Gadu.
14 |
15 | Biblioteka została napisana w języku C i jest niezależna od systemu
16 | operacyjnego czy środowiska. Pracuje pod systemami operacyjnymi zgodnymi
17 | z POSIX, również BeOS i Win32. Używana jest w aplikacjach konsolowych,
18 | jak i graficznych GTK+ i Qt.
19 |
20 | Biblioteka jest udostępniana na zasadach licencji LGPL w wersji 2.1,
21 | której treść znajduje się w pliku COPYING.
22 |
23 | Strona projektu znajduje się pod adresem http://libgadu.net/.
24 |
25 | Problemy z biblioteką można zgłaszać na stronie projektu w GitHubie pod
26 | adresem https://github.com/wojtekka/libgadu/issues. Używana wcześniej
27 | lista dyskusyjna libgadu-devel@lists.ziew.org nie jest już dostępna.
28 |
29 | Wymagania
30 | ---------
31 |
32 | Do połączeń szyfrowanych biblioteka wykorzystuje bibliotekę GnuTLS lub
33 | OpenSSL. Domyślnie OpenSSL nie jest wykorzystywany, nawet jeżeli jest
34 | zainstalowany w systemie - oprogramowanie zlinkowane z tą biblioteką nie jest
35 | kompatybilne z GPL, co powoduje problemy z łączeniem z programami na tej
36 | licencji. Aby mimo wszystko skompilować libgadu z obsługą OpenSSL, należy
37 | użyć przełącznika --with-openssl. Tak skompilowana wersja będzie tylko
38 | częściowo binarnie kompatybilna z wersją standardową: brakuje w niej symbolu
39 | gg_is_gpl_compliant, którego mogą używać aplikacje wymagające takiej
40 | licencji. Minimalna wymagana wersja biblioteki OpenSSL to 0.9.7, a biblioteki
41 | GnuTLS 2.10.0. Przy użyciu OpenSSL lub GnuTLS w wersji niższej niż 3.0 nie
42 | jest sprawdzana lista unieważnionych certyfikatów.
43 |
44 | Do przechowywania listy kontaktów na serwerze niezbędna jest biblioteka
45 | zlib.
46 |
47 | Do wygenerowania dokumentacji używany jest Doxygen. Jeśli nie jest
48 | dostępny, dokumentacja nie jest generowana.
49 |
50 | Do niektórych testów automatycznych wymagane są glibc, GnuTLS, libxml2
51 | i Perl. Jeśli nie są dostępne, niektóre testy nie będą uruchamiane.
52 | Ponadto jeden z programów do ręcznego testowania biblioteki wymaga
53 | bibliotek CURL, Expat i OpenSSL.
54 |
55 | Kompilator musi obsługiwać 64-bitowe zmienne typu long long.
56 |
57 | Podczas kompilacji wykrywana jest wersja biblioteki standardowej,
58 | ponieważ zachowanie używanych funkcji rodziny printf() zostało
59 | zmienione w ISO C99. Podczas kompilacji skrośnej nie jest możliwe
60 | automatyczne określenie wersji biblioteki na systemie docelowym, więc
61 | niezbędne jest użycie parametru --with- lub --without-c99-vsnprintf.
62 | Większość współczesnych systemów operacyjnych zawiera bibliotekę
63 | standardową zgodną ze standardem C99, więc w przypadku wątpliwości
64 | można użyć --with-c99-vsnprintf.
65 |
66 | Do asynchronicznego rozwiązywania nazw biblioteka używa procesów
67 | lub wątków pthread. Jeśli system udostępnia funkcję gethostbyname_r()
68 | działającą poprawnie w aplikacjach wielowątkowych (Linux z glibc,
69 | SunOS), zostanie ona użyta.
70 |
71 |
--------------------------------------------------------------------------------
/src/endian.c:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2001-2010 Wojtek Kaniewski
3 | * Robert J. Woźny
4 | * Arkadiusz Miśkiewicz
5 | * Tomasz Chiliński
6 | * Adam Wysocki
7 | *
8 | * This program is free software; you can redistribute it and/or modify
9 | * it under the terms of the GNU Lesser General Public License Version
10 | * 2.1 as published by the Free Software Foundation.
11 | *
12 | * This program is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU Lesser General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU Lesser General Public
18 | * License along with this program; if not, write to the Free Software
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
20 | * USA.
21 | */
22 |
23 | /**
24 | * \file endian.c
25 | *
26 | * \brief Konwersja między różnymi kolejnościami bajtów
27 | */
28 |
29 | #include "internal.h"
30 |
31 | /**
32 | * \internal Zamienia kolejność bajtów w 64-bitowym słowie.
33 | *
34 | * Ze względu na little-endianowość protokołu Gadu-Gadu, na maszynach
35 | * big-endianowych odwraca kolejność bajtów w słowie.
36 | *
37 | * \param x Liczba do zamiany
38 | *
39 | * \return Liczba z odpowiednią kolejnością bajtów
40 | *
41 | * \ingroup helper
42 | */
43 | uint64_t gg_fix64(uint64_t x)
44 | {
45 | #ifndef GG_CONFIG_BIGENDIAN
46 | return x;
47 | #else
48 | return (uint64_t)
49 | (((x & (uint64_t) 0x00000000000000ffULL) << 56) |
50 | ((x & (uint64_t) 0x000000000000ff00ULL) << 40) |
51 | ((x & (uint64_t) 0x0000000000ff0000ULL) << 24) |
52 | ((x & (uint64_t) 0x00000000ff000000ULL) << 8) |
53 | ((x & (uint64_t) 0x000000ff00000000ULL) >> 8) |
54 | ((x & (uint64_t) 0x0000ff0000000000ULL) >> 24) |
55 | ((x & (uint64_t) 0x00ff000000000000ULL) >> 40) |
56 | ((x & (uint64_t) 0xff00000000000000ULL) >> 56));
57 | #endif
58 | }
59 |
60 | /**
61 | * \internal Zamienia kolejność bajtów w 32-bitowym słowie.
62 | *
63 | * Ze względu na little-endianowość protokołu Gadu-Gadu, na maszynach
64 | * big-endianowych odwraca kolejność bajtów w słowie.
65 | *
66 | * \param x Liczba do zamiany
67 | *
68 | * \return Liczba z odpowiednią kolejnością bajtów
69 | *
70 | * \ingroup helper
71 | */
72 | uint32_t gg_fix32(uint32_t x)
73 | {
74 | #ifndef GG_CONFIG_BIGENDIAN
75 | return x;
76 | #else
77 | return (uint32_t)
78 | (((x & (uint32_t) 0x000000ffU) << 24) |
79 | ((x & (uint32_t) 0x0000ff00U) << 8) |
80 | ((x & (uint32_t) 0x00ff0000U) >> 8) |
81 | ((x & (uint32_t) 0xff000000U) >> 24));
82 | #endif
83 | }
84 |
85 | /**
86 | * \internal Zamienia kolejność bajtów w 16-bitowym słowie.
87 | *
88 | * Ze względu na little-endianowość protokołu Gadu-Gadu, na maszynach
89 | * big-endianowych zamienia kolejność bajtów w słowie.
90 | *
91 | * \param x Liczba do zamiany
92 | *
93 | * \return Liczba z odpowiednią kolejnością bajtów
94 | *
95 | * \ingroup helper
96 | */
97 | uint16_t gg_fix16(uint16_t x)
98 | {
99 | #ifndef GG_CONFIG_BIGENDIAN
100 | return x;
101 | #else
102 | return (uint16_t)
103 | (((x & (uint16_t) 0x00ffU) << 8) |
104 | ((x & (uint16_t) 0xff00U) >> 8));
105 | #endif
106 | }
107 |
--------------------------------------------------------------------------------
/test/manual/lib/oauth_parameter.c:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2008 Wojtek Kaniewski
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License Version
6 | * 2.1 as published by the Free Software Foundation.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU Lesser General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU Lesser General Public
14 | * License along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
16 | * USA.
17 | */
18 |
19 | #include
20 | #include
21 | #include "oauth_parameter.h"
22 | #include "urlencode.h"
23 |
24 | struct gg_oauth_parameter {
25 | char *key;
26 | char *value;
27 | struct gg_oauth_parameter *next;
28 | };
29 |
30 | int gg_oauth_parameter_set(gg_oauth_parameter_t **list, const char *key, const char *value)
31 | {
32 | gg_oauth_parameter_t *p, *new_p;
33 | char *new_key;
34 | char *new_value;
35 |
36 | if (value == NULL)
37 | return 0;
38 |
39 | if (list == NULL)
40 | return -1;
41 |
42 | new_key = strdup(key);
43 |
44 | if (new_key == NULL)
45 | return -1;
46 |
47 | new_value = strdup(value);
48 |
49 | if (new_value == NULL) {
50 | free(new_key);
51 | return -1;
52 | }
53 |
54 | new_p = malloc(sizeof(gg_oauth_parameter_t));
55 |
56 | if (new_p == NULL) {
57 | free(new_key);
58 | free(new_value);
59 | return -1;
60 | }
61 |
62 | memset(new_p, 0, sizeof(gg_oauth_parameter_t));
63 | new_p->key = new_key;
64 | new_p->value = new_value;
65 |
66 | if (*list != NULL) {
67 | p = *list;
68 |
69 | while (p != NULL && p->next != NULL)
70 | p = p->next;
71 |
72 | p->next = new_p;
73 | } else {
74 | *list = new_p;
75 | }
76 |
77 | return 0;
78 | }
79 |
80 | char *gg_oauth_parameter_join(gg_oauth_parameter_t *list, int header)
81 | {
82 | gg_oauth_parameter_t *p;
83 | int len = 0;
84 | char *res, *out;
85 |
86 | if (header)
87 | len += strlen("Authorization: OAuth ");
88 |
89 | for (p = list; p; p = p->next) {
90 | len += strlen(p->key);
91 |
92 | len += (header) ? 3 : 1;
93 |
94 | len += gg_urlencode_strlen(p->value);
95 |
96 | if (p->next)
97 | len += 1;
98 | }
99 |
100 | res = malloc(len + 1);
101 |
102 | if (res == NULL)
103 | return NULL;
104 |
105 | out = res;
106 |
107 | *out = 0;
108 |
109 | if (header) {
110 | strcpy(out, "Authorization: OAuth ");
111 | out += strlen(out);
112 | }
113 |
114 | for (p = list; p; p = p->next) {
115 | strcpy(out, p->key);
116 | out += strlen(p->key);
117 |
118 | strcpy(out++, "=");
119 |
120 | if (header)
121 | strcpy(out++, "\"");
122 |
123 | out = gg_urlencode_strcpy(out, p->value);
124 |
125 | if (header)
126 | strcpy(out++, "\"");
127 |
128 | if (p->next != NULL)
129 | strcpy(out++, (header) ? "," : "&");
130 | }
131 |
132 | return res;
133 | }
134 |
135 | void gg_oauth_parameter_free(gg_oauth_parameter_t *list)
136 | {
137 | while (list != NULL) {
138 | gg_oauth_parameter_t *next;
139 |
140 | next = list->next;
141 |
142 | free(list->key);
143 | free(list->value);
144 | free(list);
145 |
146 | list = next;
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/test/manual/lib/urlencode.c:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2008 Wojtek Kaniewski
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License Version
6 | * 2.1 as published by the Free Software Foundation.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU Lesser General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU Lesser General Public
14 | * License along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
16 | * USA.
17 | */
18 |
19 | #include
20 | #include
21 | #include
22 |
23 | #include "urlencode.h"
24 |
25 | #define gg_urlencode_isvalid(c) \
26 | ( \
27 | (((c) >= 'a') && ((c) <= 'z')) || \
28 | (((c) >= 'A') && ((c) <= 'Z')) || \
29 | (((c) >= '0') && ((c) <= '9')) || \
30 | ((c) == '.') || \
31 | ((c) == '-') || \
32 | ((c) == '_') || \
33 | ((c) == '~') \
34 | )
35 |
36 | static const char gg_urlencode_hex_table[] = "0123456789ABCDEF";
37 |
38 | size_t gg_urlencode_strlen(const char *p)
39 | {
40 | int len = 0;
41 |
42 | if (p == NULL)
43 | return 0;
44 |
45 | for (; *p; p++, len++) {
46 | if (!gg_urlencode_isvalid(*p))
47 | len += 2;
48 | }
49 |
50 | return len;
51 | }
52 |
53 | char *gg_urlencode_strcpy(char *buf, const char *str)
54 | {
55 | char *q;
56 | const char *p;
57 |
58 | if (str == NULL) {
59 | *buf = 0;
60 | return buf;
61 | }
62 |
63 | for (p = str, q = buf; *p; p++, q++) {
64 | if (gg_urlencode_isvalid(*p))
65 | *q = *p;
66 | else {
67 | if (*p == ' ')
68 | *q = '+';
69 | else {
70 | *q++ = '%';
71 | *q++ = gg_urlencode_hex_table[(*p >> 4) & 15];
72 | *q = gg_urlencode_hex_table[*p & 15];
73 | }
74 | }
75 | }
76 |
77 | *q = 0;
78 |
79 | return q;
80 | }
81 |
82 | char *gg_urlencode(const char *s)
83 | {
84 | char *res;
85 |
86 | res = malloc(gg_urlencode_strlen(s) + 1);
87 |
88 | if (res == NULL)
89 | return NULL;
90 |
91 | gg_urlencode_strcpy(res, s);
92 |
93 | return res;
94 | }
95 |
96 |
97 | char *gg_urlencode_printf(char *format, ...)
98 | {
99 | char *buf, *tmp;
100 | size_t size = 0;
101 | char **args;
102 | int argc = 0;
103 | va_list ap;
104 | int i, j;
105 |
106 | for (i = 0; format[i]; i++) {
107 | if (format[i] == '%') {
108 | i++;
109 | if (format[i] == '%') /* %% */
110 | size++;
111 | else if (format[i] == 's') /* %s */
112 | argc++;
113 | } else
114 | size++;
115 | }
116 |
117 | if (argc <= 0)
118 | return NULL;
119 | args = calloc(argc, sizeof(char *));
120 | if (!args)
121 | return NULL;
122 |
123 | va_start(ap, format);
124 |
125 | for (j = 0; j < argc; j++) {
126 | char *tmp = va_arg(ap, char *);
127 |
128 | size += gg_urlencode_strlen(tmp);
129 | args[j] = tmp;
130 | }
131 |
132 | va_end(ap);
133 |
134 | tmp = buf = malloc(size + 1);
135 |
136 | if (!buf) {
137 | free(args);
138 | return NULL;
139 | }
140 |
141 | *buf = '\0';
142 |
143 | for (i = 0, j = 0; format[i]; i++) {
144 | if (format[i] == '%') {
145 | i++;
146 | if (format[i] == '%') /* %% */
147 | *tmp++ = '%';
148 | else if (format[i] == 's') { /* %s */
149 | tmp = gg_urlencode_strcpy(tmp, args[j++]);
150 | }
151 | } else
152 | *tmp++ = format[i];
153 | }
154 | *tmp = '\0';
155 |
156 | free(args);
157 | return buf;
158 | }
159 |
--------------------------------------------------------------------------------
/src/libgadu.sym.in:
--------------------------------------------------------------------------------
1 | gg_add_notify
2 | gg_add_notify_ex
3 | gg_base64_decode
4 | gg_base64_encode
5 | gg_change_info
6 | gg_change_info_request_free
7 | gg_change_info_request_new
8 | gg_change_passwd
9 | gg_change_passwd2
10 | gg_change_passwd3
11 | gg_change_passwd4
12 | gg_change_status
13 | gg_change_status_descr
14 | gg_change_status_descr_time
15 | gg_change_status_flags
16 | gg_chat_create
17 | gg_chat_invite
18 | gg_chat_leave
19 | gg_chat_send_message
20 | gg_chomp
21 | gg_connect
22 | gg_crc32
23 | gg_dcc_ip
24 | gg_dcc_port
25 | gg_dcc7_accept
26 | gg_dcc7_free
27 | gg_dcc7_handle_accept
28 | gg_dcc7_handle_id
29 | gg_dcc7_handle_info
30 | gg_dcc7_handle_new
31 | gg_dcc7_handle_reject
32 | gg_dcc7_reject
33 | gg_dcc7_send_file
34 | gg_dcc7_send_file_fd
35 | gg_dcc7_watch_fd
36 | gg_dcc_fill_file_info
37 | gg_dcc_fill_file_info2
38 | gg_dcc_free
39 | gg_dcc_get_file
40 | gg_dcc_request
41 | gg_dcc_send_file
42 | gg_dcc_set_type
43 | gg_dcc_socket_create
44 | gg_dcc_voice_chat
45 | gg_dcc_voice_send
46 | gg_dcc_watch_fd
47 | gg_debug
48 | gg_debug_common
49 | gg_debug_event
50 | gg_debug_file
51 | gg_debug_handler
52 | gg_debug_handler_session
53 | gg_debug_level
54 | gg_debug_session
55 | gg_debug_state
56 | gg_event_free
57 | gg_file_hash_sha1
58 | gg_fix16
59 | gg_fix32
60 | gg_free_search
61 | gg_free_session
62 | gg_gethostbyname
63 | gg_get_line
64 | gg_global_get_resolver
65 | gg_global_set_custom_resolver
66 | gg_global_set_resolver
67 | gg_http_connect
68 | gg_http_free
69 | gg_http_free_fields
70 | gg_http_get_resolver
71 | gg_http_hash
72 | gg_http_set_custom_resolver
73 | gg_http_set_resolver
74 | gg_http_stop
75 | gg_http_watch_fd
76 | gg_image_queue_remove
77 | gg_image_reply
78 | gg_image_request
79 | gg_libgadu_check_feature
80 | gg_libgadu_version
81 | gg_local_ip
82 | gg_login
83 | gg_login_hash
84 | gg_login_hash_sha1
85 | gg_logoff
86 | gg_multilogon_disconnect
87 | gg_notify
88 | gg_notify_ex
89 | gg_ping
90 | gg_proxy_auth
91 | gg_proxy_enabled
92 | gg_proxy_host
93 | gg_proxy_http_only
94 | gg_proxy_password
95 | gg_proxy_port
96 | gg_proxy_username
97 | gg_pubdir50
98 | gg_pubdir50_add
99 | gg_pubdir50_count
100 | gg_pubdir50_free
101 | gg_pubdir50_get
102 | gg_pubdir50_handle_reply
103 | gg_pubdir50_new
104 | gg_pubdir50_next
105 | gg_pubdir50_seq
106 | gg_pubdir50_seq_set
107 | gg_pubdir50_type
108 | gg_pubdir_free
109 | gg_pubdir_watch_fd
110 | gg_read
111 | gg_read_line
112 | gg_recv_packet
113 | gg_register
114 | gg_register2
115 | gg_register3
116 | gg_remind_passwd
117 | gg_remind_passwd2
118 | gg_remind_passwd3
119 | gg_remove_notify
120 | gg_remove_notify_ex
121 | gg_resolve
122 | gg_resolve_pthread
123 | gg_resolve_pthread_cleanup
124 | gg_saprintf
125 | gg_search
126 | gg_search_request_free
127 | gg_search_request_mode_0
128 | gg_search_request_mode_1
129 | gg_search_request_mode_2
130 | gg_search_request_mode_3
131 | gg_search_watch_fd
132 | gg_send_message
133 | gg_send_message_confer
134 | gg_send_message_confer_html
135 | gg_send_message_confer_richtext
136 | gg_send_message_ctcp
137 | gg_send_message_html
138 | gg_send_message_richtext
139 | gg_send_packet
140 | gg_session_get_resolver
141 | gg_session_set_custom_resolver
142 | gg_session_set_resolver
143 | gg_socket_manager_connected
144 | gg_token
145 | gg_token_free
146 | gg_token_watch_fd
147 | gg_typing_notification
148 | gg_unregister
149 | gg_unregister2
150 | gg_unregister3
151 | gg_urlencode
152 | gg_userlist_get
153 | gg_userlist_get_free
154 | gg_userlist_get_watch_fd
155 | gg_userlist_put
156 | gg_userlist_put_free
157 | gg_userlist_put_watch_fd
158 | gg_userlist_remove
159 | gg_userlist_remove_free
160 | gg_userlist_remove_watch_fd
161 | gg_userlist_request
162 | gg_userlist100_request
163 | gg_vsaprintf
164 | gg_watch_fd
165 | gg_write
166 |
--------------------------------------------------------------------------------
/examples/token.c:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2001-2006 Wojtek Kaniewski
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License Version
6 | * 2.1 as published by the Free Software Foundation.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU Lesser General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU Lesser General Public
14 | * License along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
16 | * USA.
17 | */
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include "libgadu.h"
24 |
25 | #ifdef ASYNC
26 |
27 | #ifdef _WIN32
28 | # include
29 | #else
30 | # include
31 | # include
32 | #endif
33 | #include
34 | #include
35 |
36 | #ifndef _WIN32
37 | static void sigchld(int sig)
38 | {
39 | wait(NULL);
40 | signal(SIGCHLD, sigchld);
41 | }
42 | #endif
43 |
44 | #endif
45 |
46 | static inline int
47 | gg_mkstemp(char *path)
48 | {
49 | #if defined(_BSD_SOURCE) || defined(_SVID_SOURCE) || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 500)
50 | return (mkstemp(path) != -1);
51 | #else
52 | return (strcmp(mktemp(path), "") != 0);
53 | #endif
54 | }
55 |
56 | int main(void)
57 | {
58 | struct gg_http *h;
59 | struct gg_token *t;
60 | char path[] = "token.XXXXXX";
61 | FILE *f;
62 |
63 | gg_debug_level = 255;
64 |
65 | #ifndef ASYNC
66 |
67 | if (!(h = gg_token(0))) {
68 | printf("Błąd pobierania tokenu.\n");
69 | return 1;
70 | }
71 |
72 | #else
73 |
74 | #ifndef _WIN32
75 | signal(SIGCHLD, sigchld);
76 | #endif
77 |
78 | if (!(h = gg_token(1)))
79 | return 1;
80 |
81 | while (1) {
82 | fd_set rd, wr, ex;
83 |
84 | FD_ZERO(&rd);
85 | FD_ZERO(&wr);
86 | FD_ZERO(&ex);
87 |
88 | if ((h->check & GG_CHECK_READ))
89 | FD_SET(h->fd, &rd);
90 | if ((h->check & GG_CHECK_WRITE))
91 | FD_SET(h->fd, &wr);
92 | FD_SET(h->fd, &ex);
93 |
94 | if (select(h->fd + 1, &rd, &wr, &ex, NULL) == -1 || FD_ISSET(h->fd, &ex)) {
95 | if (errno == EINTR)
96 | continue;
97 | gg_token_free(h);
98 | perror("select");
99 | return 1;
100 | }
101 |
102 | if (FD_ISSET(h->fd, &rd) || FD_ISSET(h->fd, &wr)) {
103 | if (gg_token_watch_fd(h) == -1) {
104 | gg_token_free(h);
105 | fprintf(stderr, "Błąd połączenia.\n");
106 | return 1;
107 | }
108 | if (h->state == GG_STATE_ERROR) {
109 | gg_token_free(h);
110 | fprintf(stderr, "Błąd pobierania tokenu.\n");
111 | return 1;
112 | }
113 | if (h->state == GG_STATE_DONE)
114 | break;
115 |
116 | }
117 | }
118 |
119 | #endif
120 |
121 | t = h->data;
122 |
123 | if (!gg_mkstemp(path)) {
124 | printf("Błąd tworzenia pliku tymczasowego.\n");
125 | gg_token_free(h);
126 | return 1;
127 | }
128 |
129 | f = fopen(path, "w");
130 |
131 | if (f == NULL) {
132 | printf("Błąd otwierania pliku tymczasowego %s.\n", path);
133 | gg_token_free(h);
134 | return 1;
135 | }
136 |
137 | if (fwrite(h->body, h->body_size, 1, f) != 1) {
138 | printf("Błąd zapisu do pliku tymczasowego %s.\n", path);
139 | gg_token_free(h);
140 | fclose(f);
141 | unlink(path);
142 | return 1;
143 | }
144 |
145 | fclose(f);
146 |
147 | printf("id=%s\nwidth=%d\nheight=%d\nlength=%d\npath=%s\n", t->tokenid, t->width, t->height, t->length, path);
148 |
149 | gg_token_free(h);
150 |
151 | return 0;
152 | }
153 |
--------------------------------------------------------------------------------
/test/automatic/script/30-status.scr:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------------
2 | # Changing status
3 | #-----------------------------------------------------------------------------
4 |
5 | call {
6 | gg_change_status(session, GG_STATUS_AVAIL);
7 | }
8 |
9 | expect data (38 00 00 00, auto, 02 00 00 00, 14 00 00 00, 00 00 00 00, 00)
10 |
11 | #-----------------------------------------------------------------------------
12 |
13 | call {
14 | gg_change_status_descr(session, GG_STATUS_AVAIL_DESCR, "Test");
15 | }
16 |
17 | expect data (38 00 00 00, auto, 04 00 00 00, 14 00 00 00, 04 00 00 00, "Test" 00)
18 |
19 | #-----------------------------------------------------------------------------
20 |
21 | call {
22 | gg_change_status(session, GG_STATUS_NOT_AVAIL);
23 | }
24 |
25 | expect data (38 00 00 00, auto, 01 00 00 00, 14 00 00 00, 00 00 00 00, 00)
26 |
27 | call {
28 | // Revert state change
29 | session->state = GG_STATE_CONNECTED;
30 | }
31 |
32 | #-----------------------------------------------------------------------------
33 |
34 | call {
35 | gg_change_status_descr(session, GG_STATUS_NOT_AVAIL_DESCR, "Test");
36 | }
37 |
38 | expect data (38 00 00 00, auto, 15 00 00 00, 14 00 00 00, 04 00 00 00, "Test" 00)
39 |
40 | call {
41 | // Revert state change
42 | session->state = GG_STATE_CONNECTED;
43 | }
44 |
45 | #-----------------------------------------------------------------------------
46 |
47 | call {
48 | gg_change_status(session, GG_STATUS_BUSY);
49 | }
50 |
51 | expect data (38 00 00 00, auto, 03 00 00 00, 14 00 00 00, 00 00 00 00, 00)
52 |
53 | #-----------------------------------------------------------------------------
54 |
55 | call {
56 | gg_change_status_descr(session, GG_STATUS_BUSY_DESCR, "Test");
57 | }
58 |
59 | expect data (38 00 00 00, auto, 05 00 00 00, 14 00 00 00, 04 00 00 00, "Test" 00)
60 |
61 | #-----------------------------------------------------------------------------
62 |
63 | call {
64 | gg_change_status(session, GG_STATUS_INVISIBLE);
65 | }
66 |
67 | expect data (38 00 00 00, auto, 14 00 00 00, 14 00 00 00, 00 00 00 00, 00)
68 |
69 | #-----------------------------------------------------------------------------
70 |
71 | call {
72 | gg_change_status_descr(session, GG_STATUS_INVISIBLE_DESCR, "Test");
73 | }
74 |
75 | expect data (38 00 00 00, auto, 16 00 00 00, 14 00 00 00, 04 00 00 00, "Test" 00)
76 |
77 | #-----------------------------------------------------------------------------
78 |
79 | call {
80 | gg_change_status(session, GG_STATUS_AVAIL | GG_STATUS_FRIENDS_MASK);
81 | }
82 |
83 | expect data (38 00 00 00, auto, 02 80 00 00, 14 00 00 00, 00 00 00 00, 00)
84 |
85 | #-----------------------------------------------------------------------------
86 |
87 | call {
88 | gg_change_status_descr_time(session, GG_STATUS_AVAIL, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 0x12345678);
89 | }
90 |
91 | expect data (38 00 00 00, 0c 01 00 00, 02 00 00 00, 14 00 00 00, ff 00 00 00, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 00)
92 |
93 | #-----------------------------------------------------------------------------
94 | # Changing status flags (obsolete)
95 | #-----------------------------------------------------------------------------
96 |
97 | call {
98 | gg_change_status_flags(session, 0x11223344);
99 | gg_change_status(session, GG_STATUS_AVAIL);
100 | }
101 |
102 | expect data (38 00 00 00, auto, 02 00 00 00, 14 00 00 00, 00 00 00 00, 00)
103 |
104 | call {
105 | gg_change_status_flags(session, 0x00800001);
106 | }
107 |
108 |
--------------------------------------------------------------------------------
/test/automatic/script/12-user_data.scr:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------------
2 | # User data
3 | #-----------------------------------------------------------------------------
4 |
5 | send (44 00 00 00, auto, 44 33 22 11, 00 00 00 00)
6 |
7 | expect event GG_EVENT_USER_DATA (
8 | user_data.type == 0x11223344
9 | user_data.user_count == 0
10 | user_data.users == NULL
11 | )
12 |
13 | #-----------------------------------------------------------------------------
14 |
15 | send (44 00 00 00, auto, 44 33 22 11, 01 00 00 00, 55 44 33 22, 00 00 00 00)
16 |
17 | expect event GG_EVENT_USER_DATA (
18 | user_data.type == 0x11223344
19 | user_data.user_count == 1
20 | user_data.users != NULL
21 | user_data.users[0].uin == 0x22334455
22 | user_data.users[0].attr_count == 0
23 | user_data.users[0].attrs == NULL
24 | )
25 |
26 | #-----------------------------------------------------------------------------
27 |
28 | send (44 00 00 00, auto, 44 33 22 11, 01 00 00 00, 55 44 33 22, 01 00 00 00, 03 00 00 00, "key", 66 55 44 33, 05 00 00 00, "value")
29 |
30 | expect event GG_EVENT_USER_DATA (
31 | user_data.type == 0x11223344
32 | user_data.user_count == 1
33 | user_data.users != NULL
34 | user_data.users[0].uin == 0x22334455
35 | user_data.users[0].attr_count == 1
36 | user_data.users[0].attrs != NULL
37 | user_data.users[0].attrs[0].key == "key"
38 | user_data.users[0].attrs[0].type == 0x33445566
39 | user_data.users[0].attrs[0].value == "value"
40 | )
41 |
42 | #-----------------------------------------------------------------------------
43 | # Malformed packets
44 | #-----------------------------------------------------------------------------
45 |
46 | send (44 00 00 00, auto)
47 |
48 | expect event GG_EVENT_NONE
49 |
50 | send (44 00 00 00, auto, 44 33 22 11)
51 |
52 | expect event GG_EVENT_NONE
53 |
54 | send (44 00 00 00, auto, 44 33 22 11, 01 00 00 00)
55 |
56 | expect event GG_EVENT_NONE
57 |
58 | send (44 00 00 00, auto, 44 33 22 11, ff ff ff ff)
59 |
60 | expect event GG_EVENT_NONE
61 |
62 | send (44 00 00 00, auto, 44 33 22 11, 01 00 00 00, 55 44 33 22, 01 00 00 00)
63 |
64 | expect event GG_EVENT_NONE
65 |
66 | send (44 00 00 00, auto, 44 33 22 11, 01 00 00 00, 55 44 33 22, 01 00 00 00, 00 00 00 00)
67 |
68 | expect event GG_EVENT_NONE
69 |
70 | send (44 00 00 00, auto, 44 33 22 11, 01 00 00 00, 55 44 33 22, 01 00 00 00, 03 00 00 00)
71 |
72 | expect event GG_EVENT_NONE
73 |
74 | send (44 00 00 00, auto, 44 33 22 11, 01 00 00 00, 55 44 33 22, 01 00 00 00, ff ff ff ff)
75 |
76 | expect event GG_EVENT_NONE
77 |
78 | send (44 00 00 00, auto, 44 33 22 11, 01 00 00 00, 55 44 33 22, 01 00 00 00, 03 00 00 00, "ke")
79 |
80 | expect event GG_EVENT_NONE
81 |
82 | send (44 00 00 00, auto, 44 33 22 11, 01 00 00 00, 55 44 33 22, 01 00 00 00, 03 00 00 00, "key")
83 |
84 | expect event GG_EVENT_NONE
85 |
86 | send (44 00 00 00, auto, 44 33 22 11, 01 00 00 00, 55 44 33 22, 01 00 00 00, 03 00 00 00, "key", 66 55 44 33)
87 |
88 | expect event GG_EVENT_NONE
89 |
90 | send (44 00 00 00, auto, 44 33 22 11, 01 00 00 00, 55 44 33 22, 01 00 00 00, 03 00 00 00, "key", 66 55 44 33, 05 00 00 00)
91 |
92 | expect event GG_EVENT_NONE
93 |
94 | send (44 00 00 00, auto, 44 33 22 11, 01 00 00 00, 55 44 33 22, 01 00 00 00, 03 00 00 00, "key", 66 55 44 33, ff ff ff ff)
95 |
96 | expect event GG_EVENT_NONE
97 |
98 | send (44 00 00 00, auto, 44 33 22 11, 01 00 00 00, 55 44 33 22, 01 00 00 00, 03 00 00 00, "key", 66 55 44 33, 05 00 00 00, "val")
99 |
100 | expect event GG_EVENT_NONE
101 |
102 | send (44 00 00 00, auto, 44 33 22 11, 01 00 00 00, 55 44 33 22, 02 00 00 00, 03 00 00 00, "key", 66 55 44 33, 05 00 00 00, "value")
103 |
104 | expect event GG_EVENT_NONE
105 |
106 | send (44 00 00 00, auto, 44 33 22 11, 02 00 00 00, 55 44 33 22, 01 00 00 00, 03 00 00 00, "key", 66 55 44 33, 05 00 00 00, "value")
107 |
108 | expect event GG_EVENT_NONE
109 |
110 | #-----------------------------------------------------------------------------
111 |
112 |
113 |
--------------------------------------------------------------------------------
/test/manual/lib/hmac.c:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2008 Wojtek Kaniewski
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License Version
6 | * 2.1 as published by the Free Software Foundation.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU Lesser General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU Lesser General Public
14 | * License along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
16 | * USA.
17 | */
18 |
19 | #include "hmac.h"
20 |
21 | #ifdef HAVE_OPENSSL
22 |
23 | #include
24 | #include
25 | #include
26 |
27 | void gg_hmac_sha1(unsigned char *text, int text_len, unsigned char *key, int key_len, unsigned char *digest)
28 | {
29 | const unsigned char *res;
30 | unsigned int len;
31 |
32 | res = HMAC(EVP_sha1(), (char*) key, key_len, text, text_len, NULL, &len);
33 |
34 | memcpy(digest, res, len);
35 | }
36 |
37 | #else
38 |
39 | #include
40 | #include "sha1.h"
41 |
42 | void gg_hmac_sha1(unsigned char *text, int text_len, unsigned char *key, int key_len, unsigned char *digest)
43 | {
44 | SHA_CTX context;
45 | unsigned char k_ipad[64]; /* inner padding -
46 | * key XORd with ipad
47 | * */
48 | unsigned char k_opad[64]; /* outer padding -
49 | * key XORd with opad
50 | * */
51 | unsigned char tk[20];
52 | int i;
53 | /* if key is longer than 64 bytes reset it to key=SHA1(key) */
54 | if (key_len > 64) {
55 |
56 | SHA_CTX tctx;
57 |
58 | SHA1_Init(&tctx);
59 | SHA1_Update(&tctx, key, key_len);
60 | SHA1_Final(tk, &tctx);
61 |
62 | key = tk;
63 | key_len = 20;
64 | }
65 |
66 | /*
67 | * the HMAC_SHA1 transform looks like:
68 | *
69 | * SHA1(K XOR opad, SHA1(K XOR ipad, text))
70 | *
71 | * where K is an n byte key
72 | * ipad is the byte 0x36 repeated 64 times
73 | * opad is the byte 0x5c repeated 64 times
74 | * and text is the data being protected
75 | */
76 |
77 | /* start out by storing key in pads */
78 | memset( k_ipad, 0, sizeof k_ipad);
79 | memset( k_opad, 0, sizeof k_opad);
80 | memcpy( k_ipad, key, key_len);
81 | memcpy( k_opad, key, key_len);
82 |
83 | /* XOR key with ipad and opad values */
84 | for (i=0; i<64; i++) {
85 | k_ipad[i] ^= 0x36;
86 | k_opad[i] ^= 0x5c;
87 | }
88 | /*
89 | * perform inner SHA1
90 | */
91 | SHA1_Init(&context); /* init context for 1st
92 | * pass */
93 | SHA1_Update(&context, k_ipad, 64); /* start with inner pad */
94 | SHA1_Update(&context, text, text_len); /* then text of datagram */
95 | SHA1_Final(digest, &context); /* finish up 1st pass */
96 | /*
97 | * perform outer SHA1
98 | */
99 | SHA1_Init(&context); /* init context for 2nd
100 | * pass */
101 | SHA1_Update(&context, k_opad, 64); /* start with outer pad */
102 | SHA1_Update(&context, digest, 20); /* then results of 1st
103 | * hash */
104 | SHA1_Final(digest, &context); /* finish up 2nd pass */
105 | }
106 |
107 | #endif /* HAVE_OPENSSL */
108 |
--------------------------------------------------------------------------------
/docs/pubdir50.dox:
--------------------------------------------------------------------------------
1 | /**
2 |
3 | \defgroup pubdir50 Katalog publiczny
4 | \ingroup session
5 |
6 | \details
7 |
8 | Funkcje katalogu publicznego pozwalają wyszukiwać znajomych oraz manipulować
9 | informacjami o sobie (imię, nazwisko, miejscowość, rok urodzenia itd.). Każda
10 | operacja na katalogu publicznym wymaga skonstruowania odpowiedniego zapytania
11 | do serwera i ewentualnej obsłudze odpowiedzi.
12 |
13 | Wyszukiwanie może wyglądać następująco:
14 |
15 | \code
16 | gg_pubdir50_t zapytanie;
17 |
18 | zapytanie = gg_pubdir50_new(GG_PUBDIR50_SEARCH_REQUEST);
19 |
20 | if (!zapytanie)
21 | błąd("Brak pamięci");
22 |
23 | // Jeśli szukamy danego numeru...
24 |
25 | gg_pubdir50_add(zapytanie, GG_PUBDIR50_UIN, "123456");
26 |
27 | // ...lub kobiet o imieniu Anna...
28 |
29 | gg_pubdir50_add(zapytanie, GG_PUBDIR50_FIRSTNAME, "Anna");
30 | gg_pubdir50_add(zapytanie, GG_PUBDIR50_GENDER, GG_PUBDIR50_GENDER_FEMALE);
31 |
32 | // ...lub osób urodzonych w latach 1979-1985, aktualnie dostępnych...
33 |
34 | gg_pubdir50_add(zapytanie, GG_PUBDIR50_BIRTHYEAR, "1979 1985");
35 | gg_pubdir50_add(zapytanie, GG_PUBDIR50_START, "0");
36 | gg_pubdir50_add(zapytanie, GG_PUBDIR50_ACTIVE, GG_PUBDIR50_ACTIVE_TRUE);
37 |
38 | // ...to po ustaleniu parametrów wywołujemy
39 |
40 | gg_pubdir50(sesja, zapytanie);
41 |
42 | // Po przetworzeniu wyników zwalniamy pamięć
43 |
44 | gg_pubdir50_free(zapytanie);
45 | \endcode
46 |
47 | Jak widać, \c gg_pubdir50_new() tworzy obiekt opisujący operację katalogu,
48 | \c gg_pubdir50_add() dodaje kolejne pola zapytania. Pole zapytania jest w
49 | rzeczywiści stałą tekstową, np. \c GG_PUBDIR50_UIN to \c "FmNumber". Należy
50 | pamiętać, że wszystkie argumenty są tekstami, ale nie trzeba się przejmować
51 | alokacją pamięci — biblioteka zapamięta to, co jest potrzebne. Kodowanie
52 | tekstów jest zgodne z ustawieniem sesji. Na końcu wywołujemy funkcję
53 | \c gg_pubdir50(), która zwróci numer sekwencyjny wyszukiwania (można zachować
54 | dla późniejszego rozróżnienia wyników).
55 |
56 | Aby otrzymać wynik, należy obsłużyć zdarzenia \c GG_EVENT_PUBDIR50_SEARCH_REPLY,
57 | \c GG_EVENT_PUBDIR50_WRITE i \c GG_EVENT_PUBDIR50_READ. Dla przykładu, obsługa
58 | wyników wyszukiwania wygląda następująco:
59 |
60 | \code
61 | gg_pubdir50_t wynik;
62 | int i, ilosc;
63 |
64 | wynik = event->event.pubdir50;
65 | ilosc = gg_pubdir50_count(wynik);
66 |
67 | if (ilosc < 1) {
68 | wiadomość("Nie znaleziono");
69 | return;
70 | }
71 |
72 | for (i = 0; i < ilosc; i++) {
73 | const char *numer, *imie, *pseudo, *urodzony, *miasto, *status;
74 |
75 | numer = gg_pubdir50_get(wynik, i, GG_PUBDIR50_UIN);
76 | imie = gg_pubdir50_get(wynik, i, GG_PUBDIR50_FIRSTNAME);
77 | pseudo = gg_pubdir50_get(wynik, i, GG_PUBDIR50_NICKNAME);
78 | urodzony = gg_pubdir50_get(wynik, i, GG_PUBDIR50_BIRTHYEAR);
79 | miasto = gg_pubdir50_get(wynik, i, GG_PUBDIR50_CITY);
80 | status = gg_pubdir50_get(wynik, i, GG_PUBDIR50_STATUS);
81 |
82 | printf("Numer: %s\nImię: %s\nPseudonim: %s\n"
83 | "Urodzony: %s\nMiejscowość: %s\n",
84 | numer, imie, pseudo, urodzony, miasto);;
85 |
86 | switch ((status) ? atoi(status) : -1) {
87 | case GG_STATUS_AVAIL:
88 | printf("Dostępny\n");
89 | break;
90 | case GG_STATUS_BUSY:
91 | printf("Zajęty\n");
92 | break;
93 | default:
94 | printf("Niedostępny\n")
95 | }
96 |
97 | printf("\n");
98 | }
99 |
100 | gg_event_free(zdarzenie);
101 | \endcode
102 |
103 | Jeśli chcemy wiedzieć, od jakiego numeru zacząć wyszukiwanie, żeby dostać
104 | dalszą część, używamy \c gg_pubdir50_next(). Numer sekwencyjny otrzymamy dzięki
105 | funkcji \c gg_pubdir50_seq().
106 |
107 | \note W żadnym wypadku nie można się odwoływać do pól \c gg_pubdir50_t,
108 | ponieważ mogą się zmieniać między wersjami biblioteki. Dzięki odwoływaniu
109 | się przez funkcje, mamy pewność, że bez względu na zmiany API/ABI otrzymamy
110 | to samo. Dodatkowo, jeśli pojawią się nowe pola, wystarczy odwoływać się
111 | do nich tak jak do obecnych, za pomocą funkcji \c gg_pubdir50_add()
112 | i \c gg_pubdir50_get().
113 |
114 | */
115 |
--------------------------------------------------------------------------------
/include/network.h:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2001-2002 Wojtek Kaniewski
3 | * Robert J. Woźny
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License Version
7 | * 2.1 as published by the Free Software Foundation.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public
15 | * License along with this program; if not, write to the Free Software
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
17 | * USA.
18 | */
19 |
20 | /**
21 | * \file network.h
22 | *
23 | * \brief Makra zapewniające kompatybilność API do obsługi sieci na różnych systemach
24 | */
25 |
26 | #ifndef LIBGADU_NETWORK_H
27 | #define LIBGADU_NETWORK_H
28 |
29 | #ifdef _WIN32
30 | # include
31 | # include
32 | # include
33 | # include
34 | /* Obecnie na Win32 tylko MSVC definiuje te typy błędów. Na wypadek, gdyby
35 | * jednak Cygwin bądź MinGW zaczęły je definiować, używamy bardziej ogólnych
36 | * ifdefów. */
37 | # ifndef ECONNRESET
38 | # define ECONNRESET WSAECONNRESET
39 | # endif
40 | # ifndef EINPROGRESS
41 | # define EINPROGRESS WSAEINPROGRESS
42 | # endif
43 | # ifndef ENOTCONN
44 | # define ENOTCONN WSAENOTCONN
45 | # endif
46 | # ifndef ETIMEDOUT
47 | # define ETIMEDOUT WSAETIMEDOUT
48 | # endif
49 | # define accept gg_win32_accept
50 | # define bind gg_win32_bind
51 | # define close gg_win32_close
52 | # define connect gg_win32_connect
53 | # define gethostbyname gg_win32_gethostbyname
54 | # define getsockname gg_win32_getsockname
55 | # define getsockopt gg_win32_getsockopt
56 | # define ioctl gg_win32_ioctl
57 | # define listen gg_win32_listen
58 | # define recv gg_win32_recv
59 | # define send gg_win32_send
60 | # define setsockopt gg_win32_setsockopt
61 | # define socket gg_win32_socket
62 | # define socketpair(a, b, c, d) gg_win32_socketpair(d)
63 | int gg_win32_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
64 | int gg_win32_bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
65 | int gg_win32_close(int sockfd);
66 | int gg_win32_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
67 | struct hostent *gg_win32_gethostbyname(const char *name);
68 | int gg_win32_getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
69 | int gg_win32_getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);
70 | int gg_win32_ioctl(int d, int request, int *argp);
71 | int gg_win32_listen(int sockfd, int backlog);
72 | int gg_win32_recv(int sockfd, void *buf, size_t len, int flags);
73 | int gg_win32_send(int sockfd, const void *buf, size_t len, int flags);
74 | int gg_win32_setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
75 | int gg_win32_socket(int domain, int type, int protocol);
76 | int gg_win32_socketpair(int sv[2]);
77 |
78 | static inline void gg_win32_init_network(void)
79 | {
80 | WSADATA wsaData;
81 |
82 | if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
83 | perror("WSAStartup");
84 | exit(1);
85 | }
86 | }
87 |
88 | #else
89 | # include
90 | # include
91 | # include
92 | # include
93 | # include
94 | # include
95 | # include
96 | # ifndef FIONBIO
97 | # include
98 | # endif
99 | #endif
100 |
101 | #ifndef INADDR_NONE
102 | # define INADDR_NONE ((in_addr_t) 0xffffffff)
103 | #endif
104 |
105 | #ifndef AF_LOCAL
106 | # define AF_LOCAL AF_UNIX
107 | #endif
108 |
109 | static inline int gg_fd_set_nonblocking(int fd)
110 | {
111 | int success;
112 | #ifdef FIONBIO
113 | int one = 1;
114 | success = (ioctl(fd, FIONBIO, &one) == 0);
115 | #else
116 | success = (fcntl(fd, F_SETFL, O_NONBLOCK) == 0);
117 | #endif
118 |
119 | return success;
120 | }
121 |
122 | #endif /* LIBGADU_NETWORK_H */
123 |
--------------------------------------------------------------------------------
/test/automatic/script/40-userlist.scr:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------------
2 | # Storing contact list on server
3 | #-----------------------------------------------------------------------------
4 |
5 | call {
6 | gg_userlist_request(session, GG_USERLIST_PUT, "Test");
7 | }
8 |
9 | expect data (16 00 00 00, auto, 00, "Test")
10 |
11 | send (10 00 00 00, auto, 00)
12 |
13 | expect event GG_EVENT_USERLIST
14 |
15 | #-----------------------------------------------------------------------------
16 |
17 | call {
18 | char tmp[4096];
19 |
20 | memset(tmp, 'A', 2047);
21 | memset(tmp + 2047, 'B', 2047);
22 | strcpy(tmp + 4094, "C");
23 |
24 | gg_userlist_request(session, GG_USERLIST_PUT, tmp);
25 | }
26 |
27 | expect data (16 00 00 00, auto, 00, 41*2047)
28 |
29 | send (10 00 00 00, auto, 00)
30 |
31 | expect data (16 00 00 00, auto, 01, 42*2047)
32 |
33 | send (10 00 00 00, auto, 02)
34 |
35 | expect data (16 00 00 00, auto, 01, 43)
36 |
37 | send (10 00 00 00, auto, 02)
38 |
39 | expect event GG_EVENT_USERLIST
40 |
41 | #-----------------------------------------------------------------------------
42 | # Retrieving contact list from server
43 | #-----------------------------------------------------------------------------
44 |
45 | call {
46 | gg_userlist_request(session, GG_USERLIST_GET, NULL);
47 | }
48 |
49 | expect data (16 00 00 00, auto, 02)
50 |
51 | send (10 00 00 00, auto, 06, "Test")
52 |
53 | expect event GG_EVENT_USERLIST (
54 | userlist.type == GG_USERLIST_GET_REPLY
55 | userlist.reply == "Test"
56 | )
57 |
58 | #-----------------------------------------------------------------------------
59 |
60 | call {
61 | gg_userlist_request(session, GG_USERLIST_GET, NULL);
62 | }
63 |
64 | expect data (16 00 00 00, auto, 02)
65 |
66 | send (10 00 00 00, auto, 04, 41*2047)
67 |
68 | expect event GG_EVENT_NONE
69 |
70 | send (10 00 00 00, auto, 04, 42*2047)
71 |
72 | expect event GG_EVENT_NONE
73 |
74 | send (10 00 00 00, auto, 06, 43)
75 |
76 | expect event GG_EVENT_USERLIST {
77 | int i;
78 |
79 | if (type != GG_EVENT_USERLIST)
80 | return FALSE;
81 |
82 | if (event->userlist.type != GG_USERLIST_GET_REPLY)
83 | return FALSE;
84 |
85 | if (strlen(event->userlist.reply) != 4095)
86 | return FALSE;
87 |
88 | for (i = 0; i < 4095; i++) {
89 | int ch = (i < 2047) ? 'A' : (i < 4094) ? 'B' : 'C';
90 |
91 | if (event->userlist.reply[i] != ch)
92 | return FALSE;
93 | }
94 |
95 | return TRUE;
96 | }
97 |
98 | #-----------------------------------------------------------------------------
99 | # New version of contact list on server
100 | #-----------------------------------------------------------------------------
101 |
102 | send (5c 00 00 00, auto, 44 33 22 11)
103 |
104 | expect event GG_EVENT_USERLIST100_VERSION (
105 | userlist100_version.version == 0x11223344
106 | )
107 |
108 | #-----------------------------------------------------------------------------
109 | # Storing contact list on server
110 | #-----------------------------------------------------------------------------
111 |
112 | call {
113 | gg_userlist100_request(session, GG_USERLIST100_PUT, 0x22334455, GG_USERLIST100_FORMAT_TYPE_GG100, "");
114 | }
115 |
116 | expect data (40 00 00 00, auto, 00, 55 44 33 22, 02, 01, 78 da b3 09 49 2d 2e d1 b7 03 00 09 60 02 4a)
117 |
118 | send (41 00 00 00, auto, 10, 55 44 33 22, 02, 01)
119 |
120 | expect event GG_EVENT_USERLIST100_REPLY (
121 | userlist100_reply.type == GG_USERLIST100_REPLY_ACK
122 | userlist100_reply.version == 0x22334455
123 | userlist100_reply.format_type == GG_USERLIST100_FORMAT_TYPE_GG100
124 | )
125 |
126 | #-----------------------------------------------------------------------------
127 | # Retrieving contact list from server
128 | #-----------------------------------------------------------------------------
129 |
130 | call {
131 | gg_userlist100_request(session, GG_USERLIST100_GET, 0, GG_USERLIST100_FORMAT_TYPE_GG100, NULL);
132 | }
133 |
134 | expect data (40 00 00 00, auto, 02, 00 00 00 00, 02, 01)
135 |
136 | send (41 00 00 00, auto, 00, 55 44 33 22, 02, 01, 78 da b3 09 49 2d 2e d1 b7 03 00 09 60 02 4a)
137 |
138 | expect event GG_EVENT_USERLIST100_REPLY (
139 | userlist100_reply.type == GG_USERLIST100_REPLY_LIST
140 | userlist100_reply.version == 0x22334455
141 | userlist100_reply.format_type == GG_USERLIST100_FORMAT_TYPE_GG100
142 | userlist100_reply.reply == ""
143 | )
144 |
145 |
--------------------------------------------------------------------------------
/src/protobuf.c:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2012 Tomek Wasilczyk
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License Version
6 | * 2.1 as published by the Free Software Foundation.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU Lesser General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU Lesser General Public
14 | * License along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
16 | * USA.
17 | */
18 |
19 | /**
20 | * \file protobuf.c
21 | *
22 | * \brief Funkcje pomocnicze do obsługi formatu protocol buffers
23 | */
24 |
25 | #include "internal.h"
26 |
27 | #include "protobuf.h"
28 |
29 | #define GG_PROTOBUFF_UIN_MAXLEN 15
30 | struct _gg_protobuf_uin_buff
31 | {
32 | char data[GG_PROTOBUFF_UIN_MAXLEN + 1 + 2];
33 | };
34 |
35 | void gg_protobuf_expected(struct gg_session *gs, const char *field_name,
36 | uint32_t value, uint32_t expected)
37 | {
38 | if (value == expected) {
39 | return;
40 | }
41 | gg_debug_session(gs, GG_DEBUG_WARNING, "// gg_packet: field %s was "
42 | "expected to be %#x, but its value was %#x\n",
43 | field_name, expected, value);
44 | }
45 |
46 | int gg_protobuf_valid_chknull(struct gg_session *gs, const char *msg_name,
47 | int isNull)
48 | {
49 | if (isNull) {
50 | gg_debug_session(gs, GG_DEBUG_ERROR, "// gg_protobuf: couldn't "
51 | "unpack %s message\n", msg_name);
52 | }
53 | return !isNull;
54 | }
55 |
56 | int gg_protobuf_valid_chkunknown(struct gg_session *gs, const char *msg_name,
57 | ProtobufCMessage *base)
58 | {
59 | if (base->n_unknown_fields > 0) {
60 | gg_debug_session(gs, GG_DEBUG_WARNING, "// gg_protobuf: message"
61 | " %s had %d unknown field(s)\n",
62 | msg_name, base->n_unknown_fields);
63 | }
64 | return 1;
65 | }
66 |
67 | int gg_protobuf_send_ex(struct gg_session *gs, struct gg_event *ge, int type,
68 | void *msg, gg_protobuf_size_cb_t size_cb,
69 | gg_protobuf_pack_cb_t pack_cb)
70 | {
71 | void *buffer;
72 | size_t len;
73 | int succ = 1;
74 | enum gg_failure_t failure;
75 |
76 | len = size_cb(msg);
77 | buffer = malloc(len);
78 | if (buffer == NULL) {
79 | gg_debug_session(gs, GG_DEBUG_ERROR, "// gg_protobuf_send: out "
80 | "of memory - tried to allocate %" GG_SIZE_FMT
81 | " bytes for %#x packet\n", len, type);
82 | succ = 0;
83 | failure = GG_FAILURE_INTERNAL;
84 | } else {
85 | pack_cb(msg, buffer);
86 | succ = (-1 != gg_send_packet(gs, type, buffer, len, NULL));
87 | free(buffer);
88 | buffer = NULL;
89 | if (!succ) {
90 | failure = GG_FAILURE_WRITING;
91 | gg_debug_session(gs, GG_DEBUG_ERROR,
92 | "// gg_protobuf_send: sending packet %#x "
93 | "failed. (errno=%d, %s)\n", type, errno,
94 | strerror(errno));
95 | }
96 | }
97 |
98 | if (!succ) {
99 | gg_connection_failure(gs, ge, failure);
100 | }
101 |
102 | return succ;
103 | }
104 |
105 | void gg_protobuf_set_uin(ProtobufCBinaryData *dst, uin_t uin, gg_protobuf_uin_buff_t *buff)
106 | {
107 | char *uin_str;
108 | int uin_len;
109 | static gg_protobuf_uin_buff_t static_buffer;
110 |
111 | if (buff == NULL) {
112 | buff = &static_buffer;
113 | }
114 |
115 | uin_str = buff->data + 2;
116 | uin_len = snprintf(uin_str, GG_PROTOBUFF_UIN_MAXLEN + 1, "%u", uin);
117 |
118 | buff->data[0] = 0x01; /* magic: 0x00 lub 0x01 */
119 | buff->data[1] = uin_len;
120 |
121 | dst->len = uin_len + 2;
122 | dst->data = (uint8_t*)&buff->data;
123 | }
124 |
125 | uin_t gg_protobuf_get_uin(ProtobufCBinaryData uin_data)
126 | {
127 | uint8_t magic;
128 | size_t uin_len;
129 | const char *uin_str;
130 | uin_t uin;
131 |
132 | magic = (uin_data.len > 0) ? uin_data.data[0] : 0;
133 | uin_len = (uin_data.len > 1) ? uin_data.data[1] : 0;
134 |
135 | if (uin_data.len != uin_len + 2 || uin_len > 10) {
136 | gg_debug(GG_DEBUG_ERROR, "// gg_protobuf_get_uin: "
137 | "invalid length\n");
138 | return 0;
139 | }
140 | if (magic != 0) {
141 | gg_debug(GG_DEBUG_WARNING, "// gg_protobuf_get_uin: "
142 | "unexpected magic value=%#x\n", magic);
143 | }
144 |
145 | uin_str = (char*)(uin_data.data + 2);
146 | uin = gg_str_to_uin(uin_str, uin_len);
147 |
148 | if (uin == 0) {
149 | gg_debug(GG_DEBUG_ERROR, "// gg_protobuf_get_uin: "
150 | "invalid uin\n");
151 | }
152 | return uin;
153 | }
154 |
--------------------------------------------------------------------------------
/test/manual/lib/base64.c:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2008 Wojtek Kaniewski
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License Version
6 | * 2.1 as published by the Free Software Foundation.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU Lesser General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU Lesser General Public
14 | * License along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
16 | * USA.
17 | */
18 |
19 | #include
20 | #include
21 |
22 | #include "config.h"
23 |
24 | #include "base64.h"
25 |
26 | #ifdef HAVE_OPENSSL
27 |
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 |
34 | char *gg_base64_encode2(const char *input, ssize_t len)
35 | {
36 | BIO *bmem, *b64;
37 | BUF_MEM *bptr;
38 | char *buf;
39 |
40 | if (len == -1)
41 | len = strlen(input);
42 |
43 | b64 = BIO_new(BIO_f_base64());
44 | bmem = BIO_new(BIO_s_mem());
45 | b64 = BIO_push(b64, bmem);
46 | BIO_write(b64, input, len);
47 | BIO_flush(b64);
48 | BIO_get_mem_ptr(b64, &bptr);
49 |
50 | buf = malloc(bptr->length);
51 | memcpy(buf, bptr->data, bptr->length - 1);
52 | buf[bptr->length - 1] = 0;
53 |
54 | BIO_free_all(b64);
55 |
56 | return buf;
57 | }
58 |
59 | #else /* HAVE_OPENSSL */
60 |
61 | /**
62 | * \internal Zestaw znaków kodowania base64.
63 | */
64 | static char gg_base64_charset[] =
65 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
66 |
67 | /**
68 | * Koduje ciąg znaków do base64.
69 | *
70 | * Wynik funkcji należy zwolnić za pomocą \c free.
71 | *
72 | * \param buf Bufor z danami do zakodowania
73 | * \param len Rozmiar bufora lub -1 jesli to zwykly string
74 | *
75 | * \return Zaalokowany bufor z zakodowanymi danymi
76 | *
77 | * \ingroup helper
78 | */
79 | char *gg_base64_encode2(const char *buf, ssize_t len)
80 | {
81 | char *out, *res;
82 | unsigned int i = 0, j = 0, k = 0;
83 |
84 | if (len == -1)
85 | len = strlen(buf);
86 |
87 | res = out = malloc((len / 3 + 1) * 4 + 2);
88 |
89 | if (!res)
90 | return NULL;
91 |
92 | while (j < (size_t)len) {
93 | switch (i % 4) {
94 | case 0:
95 | k = (buf[j] & 252) >> 2;
96 | break;
97 | case 1:
98 | if (j+1 < (size_t)len)
99 | k = ((buf[j] & 3) << 4) | ((buf[j + 1] & 240) >> 4);
100 | else
101 | k = (buf[j] & 3) << 4;
102 |
103 | j++;
104 | break;
105 | case 2:
106 | if (j+1 < (size_t)len)
107 | k = ((buf[j] & 15) << 2) | ((buf[j + 1] & 192) >> 6);
108 | else
109 | k = (buf[j] & 15) << 2;
110 |
111 | j++;
112 | break;
113 | case 3:
114 | k = buf[j++] & 63;
115 | break;
116 | }
117 | *out++ = gg_base64_charset[k];
118 | i++;
119 | }
120 |
121 | if (i % 4)
122 | for (j = 0; j < 4 - (i % 4); j++, out++)
123 | *out = '=';
124 |
125 | *out = 0;
126 |
127 | return res;
128 | }
129 |
130 | /**
131 | * Dekoduje ciąg znaków zapisany w base64.
132 | *
133 | * Wynik funkcji należy zwolnić za pomocą \c free.
134 | *
135 | * \param buf Bufor źródłowy z danymi do zdekodowania
136 | *
137 | * \return Zaalokowany bufor ze zdekodowanymi danymi
138 | *
139 | * \ingroup helper
140 | */
141 | char *gg_base64_decode(const char *buf)
142 | {
143 | char *res, *save, *foo, val;
144 | const char *end;
145 | unsigned int index = 0;
146 |
147 | if (!buf)
148 | return NULL;
149 |
150 | save = res = calloc(1, (strlen(buf) / 4 + 1) * 3 + 2);
151 |
152 | if (!save)
153 | return NULL;
154 |
155 | end = buf + strlen(buf);
156 |
157 | while (*buf && buf < end) {
158 | if (*buf == '\r' || *buf == '\n') {
159 | buf++;
160 | continue;
161 | }
162 | if (!(foo = strchr(gg_base64_charset, *buf)))
163 | foo = gg_base64_charset;
164 | val = (int)(foo - gg_base64_charset);
165 | buf++;
166 | switch (index) {
167 | case 0:
168 | *res |= val << 2;
169 | break;
170 | case 1:
171 | *res++ |= val >> 4;
172 | *res |= val << 4;
173 | break;
174 | case 2:
175 | *res++ |= val >> 2;
176 | *res |= val << 6;
177 | break;
178 | case 3:
179 | *res++ |= val;
180 | break;
181 | }
182 | index++;
183 | index %= 4;
184 | }
185 | *res = 0;
186 |
187 | return save;
188 | }
189 |
190 | #endif /* HAVE_OPENSSL */
191 |
--------------------------------------------------------------------------------
/test/automatic/protocol.txt:
--------------------------------------------------------------------------------
1 | Jak to działa
2 | -------------
3 |
4 | Program testuje zgodność z protokołem Gadu-Gadu za pomocą prostych regułek
5 | opisujących akcje (wywołanie funkcji, otrzymanie pakiet od serwera)
6 | i spodziewane reakcje (wysłanie pakietu do serwera, wywołanie zdarzenia).
7 | Nie wymaga dostępu do prawdziwego serwera, ponieważ program symuluje serwer
8 | (za pomocą regułek, sam jedynie potrafi analizować przychodzące pakiety)
9 | na lokalnym porcie 17219.
10 |
11 | Dostępne akcje:
12 |
13 | 1. login (parametr = wartość, ...)
14 |
15 | Logowanie do serwera z podanymi parametrami gg_login_params. Parametry
16 | podaje się w jednej linii oddzielone przecinkiem. Adresy IP można podawać
17 | w normalnej postaci, zostaną one odpowiednio zamienione. Przykład:
18 |
19 | login (uin = 123456789, password = "qwerty", external_ip = 127.0.0.1)
20 |
21 | 2. logoff
22 |
23 | Rozłączenie z serwerem.
24 |
25 | 3. send (11 22 33 44 ...)
26 |
27 | Wysyła pakiet do biblioteki. Poszczególne liczby heksadecymalne (bez "0x")
28 | można oddzielać spacjami i/lub przecinkami dla czytelnego pogrupowania.
29 | Pakiet musi zawierać poprawny nagłówek. Docelowo trzeba będzie stworzyć
30 | mechanizm do łatwiejszego przekazywania liczb 32-bitowych, 16-bitowych
31 | i ciągów znaków. Jeśli na pozycji 4 pojawi się słowo "auto", zostanie tam
32 | umieszczony rozmiar pozostałej części pakietu w postaci 32-bitowej liczby
33 | little-endian. Można umieszczać ciągi znaków w cudzysłowach, bez spacji
34 | i bez znaków kontrolnych. Przykład:
35 |
36 | send (03 00 00 00, 00 00 00 00)
37 | send (10 00 00 00, auto, "Ala" 20 "ma" 20 "kota" 00)
38 |
39 | 4. call {
40 | // kod C
41 | }
42 |
43 | Wywołuje funkcje biblioteki. Kod C jest kopiowany dosłownie i ubierany
44 | w definicję funkcji, więc może zawierać dowolny kod języka C: deklaracje
45 | zmiennych, instrukcje warunkowe itd. Struktura sesji jest zdefioniowana
46 | jako parametr funkcji o nazwie "session". Początkowy nawias klamrowy musi
47 | znajdować się na końcu linii z nazwą regułki, a końcowy na początku linii.
48 | Przykład:
49 |
50 | call {
51 | printf("Hello, world!\n");
52 | gg_change_status(session, GG_STATUS_BUSY);
53 | }
54 |
55 | Dostępne reakcje:
56 |
57 | 1. expect connect
58 |
59 | Oczekuje na połączenie z serwerem. MUSI występować po akcji login.
60 |
61 | 2. expect disconnect
62 |
63 | Oczekuje na rozłączenie z serwerem. MUSI występować po akcji logout.
64 |
65 | 3. expect data (11 22 33 44 ...)
66 |
67 | Oczekuje na pakiet od biblioteki. Poszczególne liczby heksadecymalne
68 | (bez "0x") można oddzielać spacjami i/lub przecinkami dla czytelnego
69 | pogrupowania. Bajty, których wartość ma być ignorowana oznacza się jako
70 | "xx". Pakiet musi zawierać poprawny nagłówek. Jeśli na pozycji 4 pojawi
71 | się słowo "auto", zostanie tam umieszczony rozmiar pozostałej części
72 | pakietu w postaci 32-bitowej liczby little-endian. Można umieszczać ciągi
73 | znaków w cudzysłowach, bez spacji i bez znaków kontrolnych. Przykład:
74 |
75 | expect data (20 00 00 00, 04 00 00 00, xx xx xx xx)
76 | expect data (0f 00 00 00, auto, "Ala" 20 "ma" 20 "kota" 00)
77 |
78 | 4. expect event GG_EVENT_...
79 |
80 | Oczekuje na zdarzenie od biblioteki. Pola zdarzenia nie grają roli.
81 | Przykład:
82 |
83 | expect event GG_EVENT_CONN_SUCCESS
84 |
85 | 5. expect event GG_EVENT_... (
86 | pole == wartość
87 | pole[indeks] == (typ) wartość
88 | ...
89 | )
90 |
91 | Oczekuje na zdarzenie od biblioteki, którego pola są opisane regułami.
92 | Każda reguła znajduje się w osobnej linii, nawias otwierający w linii
93 | z reakcją, nawias zamykający na początku linii. Pola muszą zawierać
94 | nazwę pola zdarzenia z unii. Dostępne są wszystkie operatory porównań
95 | języka C. Porównywanie ciągów znaków zapisuje się tak samo jak liczb,
96 | tj. operatorami == i !=. Pola zdefiniowane jako wskaźniki typu (void*)
97 | można porównywać dzięki opisaniu typu przed wartością. Adresy IP można
98 | zapisywać w normalnej postacji. Przykład:
99 |
100 | expect event GG_EVENT_MSG (
101 | msg.sender != 0
102 | msg.message == "Ala ma kota"
103 | msg.recipients[0] == (int) 123456
104 | )
105 |
106 | 6. expect event [GG_EVENT_...] {
107 | // kod C
108 | }
109 |
110 | Oczekuje na zdarzenie od biblioteki. Zasady dotyczące wklejania kodu C
111 | są identyczne jak dla akcji call. Typ zdarzenia jest przekazywany jako
112 | parametr "type", unia zdarzenia jako wskaźnik "event". Typ zdarzenia nie
113 | musi wystąpić. Kod musi zwrócić wartość prawdziwą jeśli zdarzenie jest
114 | poprawne. Przykład:
115 |
116 | expect event {
117 | if (type != GG_EVENT_CONN_SUCCESS && type != GG_EVENT_CONN_FAILED)
118 | return false;
119 |
120 | if (type == GG_EVENT_CONN_FALSE && event->failure == GG_FAILURE_INVALID)
121 | return false;
122 |
123 | return true;
124 | }
125 |
126 | Dodatkowe dyrektywy:
127 |
128 | 1. include nazwapliku.scr
129 |
130 | Dołącza zawartość pliku do scenariusza.
131 |
--------------------------------------------------------------------------------
/test/automatic/script/25-images.scr:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------------
2 | # Sending image request
3 | #-----------------------------------------------------------------------------
4 |
5 | call {
6 | gg_image_request(session, 0x00123456, 4, 0x784dd132);
7 | }
8 |
9 | expect data (0b 00 00 00, auto, 56 34 12 00, xx xx xx xx, 04 00 00 00, 00, 04, 04 00 00 00, 32 d1 4d 78)
10 |
11 | #-----------------------------------------------------------------------------
12 | # Receiving image reply
13 | #-----------------------------------------------------------------------------
14 |
15 | send (0a 00 00 00, auto, 56 34 12 00, 00 00 00 00, 00 00 00 00, 04 00 00 00, 00, 05, 04 00 00 00, 32 d1 4d 78, "test.txt" 00, "Test")
16 |
17 | expect event GG_EVENT_IMAGE_REPLY {
18 | return (event->image_reply.sender == 0x00123456) &&
19 | (event->image_reply.size == 4) &&
20 | (event->image_reply.crc32 == 0x784dd132) &&
21 | (strcmp(event->image_reply.filename, "test.txt") == 0) &&
22 | (memcmp(event->image_reply.image, "Test", 4) == 0);
23 | }
24 |
25 | expect data (46 00 00 00, auto, xx xx xx xx)
26 |
27 | #-----------------------------------------------------------------------------
28 | # Receiving unsolicited image reply
29 | #-----------------------------------------------------------------------------
30 |
31 | send (0a 00 00 00, auto, 56 34 12 00, 00 00 00 00, 00 00 00 00, 04 00 00 00, 00, 05, 04 00 00 00, 12 34 56 78, "junk.txt" 00, "Junk")
32 |
33 | expect event GG_EVENT_NONE
34 |
35 | expect data (46 00 00 00, auto, xx xx xx xx)
36 |
37 | #-----------------------------------------------------------------------------
38 | # Receiving multipart image reply
39 | #-----------------------------------------------------------------------------
40 |
41 | call {
42 | gg_image_request(session, 0x00123456, 8, 0x568347c8);
43 | }
44 |
45 | expect data (0b 00 00 00, auto, 56 34 12 00, xx xx xx xx, 04 00 00 00, 00, 04, 08 00 00 00, c8 47 83 56)
46 |
47 | #-----------------------------------------------------------------------------
48 |
49 | send (0a 00 00 00, auto, 56 34 12 00, 00 00 00 00, 00 00 00 00, 04 00 00 00, 00, 05, 08 00 00 00, c8 47 83 56, "test.txt" 00, "Test")
50 |
51 | expect data (46 00 00 00, auto, xx xx xx xx)
52 |
53 | send (0a 00 00 00, auto, 56 34 12 00, 00 00 00 00, 00 00 00 00, 04 00 00 00, 00, 06, 08 00 00 00, c8 47 83 56, "1234")
54 |
55 | expect event GG_EVENT_IMAGE_REPLY {
56 | return (event->image_reply.sender == 0x00123456) &&
57 | (event->image_reply.size == 8) &&
58 | (event->image_reply.crc32 == 0x568347c8) &&
59 | (strcmp(event->image_reply.filename, "test.txt") == 0) &&
60 | (memcmp(event->image_reply.image, "Test1234", 8) == 0);
61 | }
62 |
63 | expect data (46 00 00 00, auto, xx xx xx xx)
64 |
65 | #-----------------------------------------------------------------------------
66 | # Receiving image request
67 | #-----------------------------------------------------------------------------
68 |
69 | send (0a 00 00 00, auto, 56 34 12 00, 00 00 00 00, 00 00 00 00, 04 00 00 00, 00, 04, 04 00 00 00, 32 d1 4d 78)
70 |
71 | expect event GG_EVENT_IMAGE_REQUEST (
72 | image_request.sender == 0x00123456
73 | image_request.size == 4
74 | image_request.crc32 == 0x784dd132
75 | )
76 |
77 | expect data (46 00 00 00, auto, xx xx xx xx)
78 |
79 | #-----------------------------------------------------------------------------
80 | # Receiving malformed image request
81 | #-----------------------------------------------------------------------------
82 |
83 | send (0a 00 00 00, auto, 56 34 12 00, 00 00 00 00, 00 00 00 00, 04 00 00 00, 00, 02, 01 00, 42, 04, 04 00 00 00, 32 d1 4d 78)
84 |
85 | expect event GG_EVENT_NONE
86 |
87 | expect data (46 00 00 00, auto, xx xx xx xx)
88 |
89 | #-----------------------------------------------------------------------------
90 |
91 | send (0a 00 00 00, auto, 56 34 12 00, 00 00 00 00, 00 00 00 00, 04 00 00 00, 00, 01, 01 00 00 00, 11 22 33 44, 04, 04 00 00 00, 32 d1 4d 78)
92 |
93 | expect event GG_EVENT_NONE
94 |
95 | expect data (46 00 00 00, auto, xx xx xx xx)
96 |
97 | #-----------------------------------------------------------------------------
98 | # Sending image reply
99 | #-----------------------------------------------------------------------------
100 |
101 | call {
102 | gg_image_reply(session, 0x123456, "test.txt", "Test", 4);
103 | }
104 |
105 | expect data (0b 00 00 00, auto, 56 34 12 00, xx xx xx xx, 04 00 00 00, 00, 05, 04 00 00 00, 32 d1 4d 78, "test.txt" 00, "Test")
106 |
107 | #-----------------------------------------------------------------------------
108 | # Sending multipart reply
109 | #-----------------------------------------------------------------------------
110 |
111 | call {
112 | char tmp[2048];
113 |
114 | memset(tmp, 'A', sizeof(tmp));
115 |
116 | gg_image_reply(session, 0x123456, "multipart.txt", tmp, sizeof(tmp));
117 | }
118 |
119 | expect data (0b 00 00 00, auto, 56 34 12 00, xx xx xx xx, 04 00 00 00, 00, 05, 00 08 00 00, 39 20 df d5, "multipart.txt" 00, 41*1886)
120 |
121 | expect data (0b 00 00 00, auto, 56 34 12 00, xx xx xx xx, 04 00 00 00, 00, 06, 00 08 00 00, 39 20 df d5, 41*162)
122 |
123 |
--------------------------------------------------------------------------------
/test/automatic/hash.c:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2001-2006 Wojtek Kaniewski
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License Version
6 | * 2.1 as published by the Free Software Foundation.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU Lesser General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU Lesser General Public
14 | * License along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
16 | * USA.
17 | */
18 |
19 | #include "internal.h"
20 |
21 | #include
22 | #include
23 | #include
24 | #include
25 |
26 | #include "fileio.h"
27 |
28 | static inline int
29 | gg_mkstemp(char *path)
30 | {
31 | mode_t old_umask, file_mask;
32 | int ret;
33 |
34 | file_mask = S_IRWXO | S_IRWXG;
35 | old_umask = umask(file_mask);
36 | #ifdef HAVE_MKSTEMP
37 | ret = mkstemp(path);
38 | #else
39 | #ifdef _WIN32
40 | if (_mktemp_s(path, strlen(path) + 1) != 0)
41 | #else
42 | /* coverity[secure_temp : FALSE]
43 | *
44 | * mktemp may be unsafe, because it creates files with predictable
45 | * names, but it's not a real problem for automatic tests.
46 | */
47 | if (strcmp(mktemp(path), "") == 0)
48 | #endif
49 | ret = -1;
50 | else
51 | ret = open(path, O_EXCL | O_RDWR | O_CREAT, file_mask);
52 | #endif
53 | umask(old_umask);
54 |
55 | return ret;
56 | }
57 |
58 | static char *sha1_to_string(uint8_t *sha1)
59 | {
60 | static char str[41];
61 | size_t i;
62 |
63 | for (i = 0; i < 20; i++)
64 | sprintf(str + i * 2, "%02x", sha1[i]);
65 |
66 | return str;
67 | }
68 |
69 | static int sha1_compare(uint8_t *sha1, const char *str)
70 | {
71 | size_t i;
72 |
73 | for (i = 0; i < 20; i++) {
74 | unsigned int byte;
75 |
76 | sscanf(str + i * 2, "%02x", &byte);
77 |
78 | if (byte != sha1[i])
79 | return 0;
80 | }
81 |
82 | return 1;
83 | }
84 |
85 | struct login_hash {
86 | const char *password;
87 | uint32_t seed;
88 | const char *expect;
89 | };
90 |
91 | struct login_hash login_hashes[] = {
92 | { "AAAA", 0x41414141, "c08598945e566e4e53cf3654c922fa98003bf2f9" },
93 | { "test", 0x41424344, "459d3fbcfd3a91ef4fe64e151d950e0997af4ba4" },
94 | };
95 |
96 | static void test_login_hash(const char *password, uint32_t seed, const char *expect)
97 | {
98 | uint8_t result[20];
99 |
100 | if (gg_login_hash_sha1_2(password, seed, result) == -1) {
101 | fprintf(stderr, "gg_login_hash_sha1_2() failed for \"%s\", 0x%08x\n", password, seed);
102 | exit(1);
103 | }
104 |
105 | if (!sha1_compare(result, expect)) {
106 | printf("hash failed for \"%s\", 0x%08x, expected %s, got %s\n",
107 | password, seed, expect, sha1_to_string(result));
108 | exit(1);
109 | }
110 | }
111 |
112 | struct file_hash {
113 | unsigned int megs;
114 | const char *expect;
115 | };
116 |
117 | struct file_hash file_hashes[] = {
118 | { 0, "da39a3ee5e6b4b0d3255bfef95601890afd80709" },
119 | { 1, "ad03e557eeed1f108ed9f5a54f9d0255f69c168e" },
120 | { 2, "45afb38af4ba1e161f6fde18818a4acbe87a1c88" },
121 | { 9, "940a5611380985416844aa6fb3767b38e4aac59f" },
122 | { 10, "8f7659b0fa3994fcce2be062bbea0d183e9bc44e" },
123 | { 11, "43c12a04edda27d2a87c8c85aa5680bf36bdb0c0" },
124 | { 12, "f40bdc59b7b073735e6e53ce9fa67f17978ef236" },
125 | };
126 |
127 | static void test_file_hash(unsigned int megs, const char *expect)
128 | {
129 | int fd;
130 | size_t i;
131 | char name[32];
132 | uint8_t result[20];
133 |
134 | strcpy(name, "hashdata.XXXXXX");
135 |
136 | fd = gg_mkstemp(name);
137 |
138 | if (fd == -1) {
139 | fprintf(stderr, "Unable to create temporary file\n");
140 | exit(1);
141 | }
142 |
143 | for (i = 1; i <= megs; i++) {
144 | unsigned char j;
145 |
146 | if (lseek(fd, i * 1048756 - 1, SEEK_SET) == (off_t) -1) {
147 | fprintf(stderr, "Unable to seek past end of file\n");
148 | goto fail;
149 | }
150 |
151 | j = i;
152 |
153 | if (write(fd, &j, sizeof(j)) != sizeof(j)) {
154 | fprintf(stderr, "Unable to write past end of file\n");
155 | goto fail;
156 | }
157 | }
158 |
159 | if (gg_file_hash_sha1(fd, result) == -1) {
160 | fprintf(stderr, "gg_file_hash_sha1() failed for %d megs\n", megs);
161 | goto fail;
162 | }
163 |
164 | if (!sha1_compare(result, expect)) {
165 | printf("hash failed for %d mesgs, expected %s, got %s\n", megs, expect, sha1_to_string(result));
166 | goto fail;
167 | }
168 |
169 | close(fd);
170 | unlink(name);
171 | return;
172 |
173 | fail:
174 | close(fd);
175 | unlink(name);
176 | exit(1);
177 | }
178 |
179 | int main(void)
180 | {
181 | unsigned int i;
182 |
183 | for (i = 0; i < sizeof(login_hashes) / sizeof(login_hashes[0]); i++)
184 | test_login_hash(login_hashes[i].password, login_hashes[i].seed, login_hashes[i].expect);
185 |
186 | for (i = 0; i < sizeof(file_hashes) / sizeof(file_hashes[0]); i++)
187 | test_file_hash(file_hashes[i].megs, file_hashes[i].expect);
188 |
189 | return 0;
190 | }
191 |
--------------------------------------------------------------------------------
/test/manual/userlist.c:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2001-2006 Wojtek Kaniewski
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License Version
6 | * 2.1 as published by the Free Software Foundation.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU Lesser General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU Lesser General Public
14 | * License along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
16 | * USA.
17 | */
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 |
27 | #include "libgadu.h"
28 | #include "network.h"
29 | #include "userconfig.h"
30 |
31 | static void usage(const char *argv0)
32 | {
33 | fprintf(stderr, "usage: %s [OPTIONS]\n"
34 | "\n"
35 | "Options:\n"
36 | " -c Check userlist version\n"
37 | " -p Put userlist content from stdin to server\n"
38 | " -g Get userlist content from server to stdout\n"
39 | " -r Remove userlist content from server\n"
40 | " -v VERSION Set userlist version for -p, -r or -g\n"
41 | " -f FORMAT Set userlist format (7.0, 10.0 or numeric value)\n"
42 | " -d Print debug messages\n"
43 | "\n"
44 | "Note: Put and remove operations require correct userlist version.\n"
45 | "\n", argv0);
46 | }
47 |
48 | int main(int argc, char **argv)
49 | {
50 | struct gg_session *gs;
51 | struct gg_login_params glp;
52 | int opt;
53 | int format = GG_USERLIST100_FORMAT_TYPE_GG100;
54 | int version = 0;
55 | enum { MODE_NONE, MODE_VERSION, MODE_GET, MODE_PUT, MODE_REMOVE } mode = MODE_NONE;
56 | int type = GG_USERLIST100_GET;
57 | char *content = NULL;
58 | int debug = 0;
59 | int res = 0;
60 |
61 | #ifdef _WIN32
62 | gg_win32_init_network();
63 | #endif
64 |
65 | while ((opt = getopt(argc, argv, "cv:gpf:hdr")) != -1) {
66 | switch (opt) {
67 | case 'v':
68 | version = atoi(optarg);
69 | break;
70 |
71 | case 'c':
72 | mode = MODE_VERSION;
73 | type = GG_USERLIST100_GET;
74 | break;
75 |
76 | case 'g':
77 | mode = MODE_GET;
78 | type = GG_USERLIST100_GET;
79 | break;
80 |
81 | case 'p':
82 | mode = MODE_PUT;
83 | type = GG_USERLIST100_PUT;
84 | break;
85 |
86 | case 'r':
87 | mode = MODE_REMOVE;
88 | type = GG_USERLIST100_PUT;
89 | free(content);
90 | content = strdup(" ");
91 | break;
92 |
93 | case 'f':
94 | if (strcmp(optarg, "7.0") == 0)
95 | format = GG_USERLIST100_FORMAT_TYPE_GG70;
96 | else if (strcmp(optarg, "10.0") == 0)
97 | format = GG_USERLIST100_FORMAT_TYPE_GG100;
98 | else
99 | format = atoi(optarg);
100 | break;
101 |
102 | case 'd':
103 | debug = 1;
104 | break;
105 |
106 | case 'h':
107 | usage(argv[0]);
108 | exit(0);
109 | }
110 | }
111 |
112 | if (mode == MODE_NONE) {
113 | usage(argv[0]);
114 | exit(1);
115 | }
116 |
117 | if (config_read() == -1) {
118 | perror("config");
119 | exit(1);
120 | }
121 |
122 | #ifndef _WIN32
123 | signal(SIGPIPE, SIG_IGN);
124 | #endif
125 |
126 | if (debug) {
127 | gg_debug_file = stderr;
128 | gg_debug_level = ~0;
129 | }
130 |
131 | memset(&glp, 0, sizeof(glp));
132 | glp.uin = config_uin;
133 | glp.password = config_password;
134 |
135 | gs = gg_login(&glp);
136 |
137 | if (gs == NULL) {
138 | perror("gg_login");
139 | exit(1);
140 | }
141 |
142 | if (mode == MODE_PUT) {
143 | char buf[1024];
144 |
145 | while (fgets(buf, sizeof(buf), stdin)) {
146 | char *tmp;
147 | size_t len;
148 |
149 | len = (content == NULL) ? 0 : strlen(content);
150 |
151 | tmp = realloc(content, len + strlen(buf) + 1);
152 |
153 | if (tmp == NULL) {
154 | perror("realloc");
155 | free(content);
156 | gg_free_session(gs);
157 | exit(1);
158 | }
159 |
160 | content = tmp;
161 | strcpy(content + len, buf);
162 | }
163 | }
164 |
165 | gg_notify(gs, NULL, 0);
166 |
167 | if (gg_userlist100_request(gs, type, version, format, content) == -1) {
168 | perror("gg_userlist100_request");
169 | gg_free_session(gs);
170 | free(content);
171 | exit(1);
172 | }
173 |
174 | for (;;) {
175 | struct gg_event *ge;
176 |
177 | ge = gg_watch_fd(gs);
178 |
179 | if (ge == NULL) {
180 | perror("gg_watch_fd");
181 | free(content);
182 | gg_free_session(gs);
183 | exit(1);
184 | }
185 |
186 | if (ge->type == GG_EVENT_USERLIST100_REPLY) {
187 | switch (ge->event.userlist100_reply.type) {
188 | case GG_USERLIST100_REPLY_REJECT:
189 | fprintf(stderr, "Rejected\n");
190 | res = 1;
191 | break;
192 | case GG_USERLIST100_REPLY_LIST:
193 | if (mode == MODE_VERSION)
194 | printf("%d\n", ge->event.userlist100_reply.version);
195 | else
196 | printf("%s", ge->event.userlist100_reply.reply);
197 | break;
198 | case GG_USERLIST100_REPLY_UPTODATE:
199 | case GG_USERLIST100_REPLY_ACK:
200 | res = 0;
201 | break;
202 | }
203 |
204 | gg_event_free(ge);
205 |
206 | break;
207 | }
208 |
209 | gg_event_free(ge);
210 | }
211 |
212 | gg_logoff(gs);
213 | free(content);
214 | gg_free_session(gs);
215 | config_free();
216 |
217 | return res;
218 | }
219 |
--------------------------------------------------------------------------------
/src/protobuf-c.c.patch:
--------------------------------------------------------------------------------
1 | --- protobuf-c.c.ori 2016-01-30 00:54:28.000000000 +0000
2 | +++ protobuf-c.c 2016-05-02 13:48:47.033083213 +0100
3 | @@ -48,6 +48,9 @@
4 | #include /* for malloc, free */
5 | #include /* for strcmp, strlen, memcpy, memmove, memset */
6 |
7 | +/* Pull WORDS_BIGENDIAN etc */
8 | +#include "config.h"
9 | +
10 | #include "protobuf-c.h"
11 |
12 | #define TRUE 1
13 | @@ -285,13 +288,13 @@
14 | {
15 | if (v < 0) {
16 | return 10;
17 | - } else if (v < (1UL << 7)) {
18 | + } else if (v < (1L << 7)) {
19 | return 1;
20 | - } else if (v < (1UL << 14)) {
21 | + } else if (v < (1L << 14)) {
22 | return 2;
23 | - } else if (v < (1UL << 21)) {
24 | + } else if (v < (1L << 21)) {
25 | return 3;
26 | - } else if (v < (1UL << 28)) {
27 | + } else if (v < (1L << 28)) {
28 | return 4;
29 | } else {
30 | return 5;
31 | @@ -1761,9 +1764,11 @@
32 | }
33 | return rv;
34 |
35 | +#if !defined(WORDS_BIGENDIAN)
36 | no_packing_needed:
37 | buffer->append(buffer, rv, array);
38 | return rv;
39 | +#endif
40 | }
41 |
42 | static size_t
43 | @@ -2078,6 +2083,10 @@
44 | latter_msg,
45 | fields[i].
46 | quantifier_offset);
47 | + protobuf_c_boolean need_to_merge = FALSE;
48 | + void *earlier_elem;
49 | + void *latter_elem;
50 | + const void *def_val;
51 |
52 | if (fields[i].flags & PROTOBUF_C_FIELD_FLAG_ONEOF) {
53 | if (*latter_case_p == 0) {
54 | @@ -2099,12 +2108,11 @@
55 | field = &fields[i];
56 | }
57 |
58 | - protobuf_c_boolean need_to_merge = FALSE;
59 | - void *earlier_elem =
60 | + earlier_elem =
61 | STRUCT_MEMBER_P(earlier_msg, field->offset);
62 | - void *latter_elem =
63 | + latter_elem =
64 | STRUCT_MEMBER_P(latter_msg, field->offset);
65 | - const void *def_val = field->default_value;
66 | + def_val = field->default_value;
67 |
68 | switch (field->type) {
69 | case PROTOBUF_C_TYPE_MESSAGE: {
70 | @@ -2487,6 +2495,7 @@
71 | *oneof_case);
72 | const ProtobufCFieldDescriptor *old_field =
73 | message->descriptor->fields + field_index;
74 | + size_t el_size = sizeof_elt_in_repeated_array(old_field->type);
75 | switch (old_field->type) {
76 | case PROTOBUF_C_TYPE_STRING: {
77 | char **pstr = member;
78 | @@ -2516,7 +2525,6 @@
79 | break;
80 | }
81 |
82 | - size_t el_size = sizeof_elt_in_repeated_array(old_field->type);
83 | memset (member, 0, el_size);
84 | }
85 | if (!parse_required_member (scanned_member, member, allocator, TRUE))
86 | @@ -3070,6 +3078,7 @@
87 | field->quantifier_offset);
88 | if (*n_ptr != 0) {
89 | unsigned n = *n_ptr;
90 | + void *a;
91 | *n_ptr = 0;
92 | assert(rv->descriptor != NULL);
93 | #define CLEAR_REMAINING_N_PTRS() \
94 | @@ -3079,7 +3088,7 @@
95 | if (field->label == PROTOBUF_C_LABEL_REPEATED) \
96 | STRUCT_MEMBER (size_t, rv, field->quantifier_offset) = 0; \
97 | }
98 | - void *a = do_alloc(allocator, siz * n);
99 | + a = do_alloc(allocator, siz * n);
100 | if (!a) {
101 | CLEAR_REMAINING_N_PTRS();
102 | goto error_cleanup;
103 | @@ -3152,11 +3161,13 @@
104 | protobuf_c_message_free_unpacked(ProtobufCMessage *message,
105 | ProtobufCAllocator *allocator)
106 | {
107 | + const ProtobufCMessageDescriptor *desc;
108 | + unsigned f;
109 | +
110 | if (message == NULL)
111 | return;
112 |
113 | - const ProtobufCMessageDescriptor *desc = message->descriptor;
114 | - unsigned f;
115 | + desc = message->descriptor;
116 |
117 | ASSERT_IS_MESSAGE(message);
118 |
119 | @@ -3245,6 +3256,8 @@
120 | protobuf_c_boolean
121 | protobuf_c_message_check(const ProtobufCMessage *message)
122 | {
123 | + unsigned i;
124 | +
125 | if (!message ||
126 | !message->descriptor ||
127 | message->descriptor->magic != PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC)
128 | @@ -3252,7 +3265,6 @@
129 | return FALSE;
130 | }
131 |
132 | - unsigned i;
133 | for (i = 0; i < message->descriptor->n_fields; i++) {
134 | const ProtobufCFieldDescriptor *f = message->descriptor->fields + i;
135 | ProtobufCType type = f->type;
136 | @@ -3375,11 +3387,13 @@
137 | protobuf_c_enum_descriptor_get_value_by_name(const ProtobufCEnumDescriptor *desc,
138 | const char *name)
139 | {
140 | + unsigned start = 0;
141 | + unsigned count;
142 | +
143 | if (desc == NULL || desc->values_by_name == NULL)
144 | return NULL;
145 |
146 | - unsigned start = 0;
147 | - unsigned count = desc->n_value_names;
148 | + count = desc->n_value_names;
149 |
150 | while (count > 1) {
151 | unsigned mid = start + count / 2;
152 | @@ -3413,12 +3427,14 @@
153 | protobuf_c_message_descriptor_get_field_by_name(const ProtobufCMessageDescriptor *desc,
154 | const char *name)
155 | {
156 | + unsigned start = 0;
157 | + unsigned count;
158 | + const ProtobufCFieldDescriptor *field;
159 | +
160 | if (desc == NULL || desc->fields_sorted_by_name == NULL)
161 | return NULL;
162 |
163 | - unsigned start = 0;
164 | - unsigned count = desc->n_fields;
165 | - const ProtobufCFieldDescriptor *field;
166 | + count = desc->n_fields;
167 |
168 | while (count > 1) {
169 | unsigned mid = start + count / 2;
170 | @@ -3455,11 +3471,13 @@
171 | protobuf_c_service_descriptor_get_method_by_name(const ProtobufCServiceDescriptor *desc,
172 | const char *name)
173 | {
174 | + unsigned start = 0;
175 | + unsigned count;
176 | +
177 | if (desc == NULL || desc->method_indices_by_name == NULL)
178 | return NULL;
179 |
180 | - unsigned start = 0;
181 | - unsigned count = desc->n_methods;
182 | + count = desc->n_methods;
183 |
184 | while (count > 1) {
185 | unsigned mid = start + count / 2;
186 |
--------------------------------------------------------------------------------
/test/automatic/script/50-pubdir.scr:
--------------------------------------------------------------------------------
1 | #-----------------------------------------------------------------------------
2 | # Search request
3 | #-----------------------------------------------------------------------------
4 |
5 | call {
6 | gg_pubdir50_t request;
7 |
8 | if (!(request = gg_pubdir50_new(GG_PUBDIR50_SEARCH_REQUEST)))
9 | return;
10 |
11 | gg_pubdir50_add(request, GG_PUBDIR50_UIN, "123456");
12 | gg_pubdir50_add(request, GG_PUBDIR50_FIRSTNAME, "Jan");
13 | gg_pubdir50_add(request, GG_PUBDIR50_LASTNAME, "Kowalski");
14 | gg_pubdir50_add(request, GG_PUBDIR50_NICKNAME, "Janko Muzykant");
15 | gg_pubdir50_add(request, GG_PUBDIR50_BIRTHYEAR, "1900 2000");
16 | gg_pubdir50_add(request, GG_PUBDIR50_CITY, "Warszawa");
17 | gg_pubdir50_add(request, GG_PUBDIR50_GENDER, GG_PUBDIR50_GENDER_MALE);
18 | gg_pubdir50_add(request, GG_PUBDIR50_ACTIVE, GG_PUBDIR50_ACTIVE_TRUE);
19 | gg_pubdir50_add(request, GG_PUBDIR50_FAMILYNAME, "Nowak");
20 | gg_pubdir50_add(request, GG_PUBDIR50_FAMILYCITY, "Zielonka");
21 | gg_pubdir50_add(request, GG_PUBDIR50_START, "234567");
22 |
23 | gg_pubdir50(session, request);
24 |
25 | gg_pubdir50_free(request);
26 | }
27 |
28 | expect data (14 00 00 00, auto, 03, xx xx xx xx, "FmNumber" 00, "123456" 00, "firstname" 00, "Jan" 00, "lastname" 00, "Kowalski" 00, "nickname" 00, "Janko" 20 "Muzykant" 00, "birthyear" 00, "1900" 20 "2000" 00, "city" 00, "Warszawa" 00, "gender" 00, "2" 00, "ActiveOnly" 00, "1" 00, "familyname" 00, "Nowak" 00, "familycity" 00, "Zielonka" 00, "fmstart" 00, "234567" 00)
29 |
30 | #-----------------------------------------------------------------------------
31 |
32 | call {
33 | gg_pubdir50_t request;
34 |
35 | if (!(request = gg_pubdir50_new(GG_PUBDIR50_SEARCH_REQUEST)))
36 | return;
37 |
38 | gg_pubdir50_add(request, GG_PUBDIR50_FIRSTNAME, "Anna");
39 | gg_pubdir50_add(request, GG_PUBDIR50_GENDER, GG_PUBDIR50_GENDER_FEMALE);
40 | gg_pubdir50_seq_set(request, 0x12345678);
41 |
42 | gg_pubdir50(session, request);
43 |
44 | gg_pubdir50_free(request);
45 | }
46 |
47 | expect data (14 00 00 00, auto, 03, 78 56 34 12, "firstname" 00, "Anna" 00, "gender" 00, "1" 00)
48 |
49 | #-----------------------------------------------------------------------------
50 | # Retrieving own information
51 | #-----------------------------------------------------------------------------
52 |
53 | call {
54 | gg_pubdir50_t request;
55 |
56 | if (!(request = gg_pubdir50_new(GG_PUBDIR50_READ)))
57 | return;
58 |
59 | gg_pubdir50(session, request);
60 |
61 | gg_pubdir50_free(request);
62 | }
63 |
64 | expect data (14 00 00 00, auto, 02, xx xx xx xx)
65 |
66 | #-----------------------------------------------------------------------------
67 | # Setting own information
68 | #-----------------------------------------------------------------------------
69 |
70 | call {
71 | gg_pubdir50_t request;
72 |
73 | if (!(request = gg_pubdir50_new(GG_PUBDIR50_WRITE)))
74 | return;
75 |
76 | gg_pubdir50_add(request, GG_PUBDIR50_FIRSTNAME, "Jan");
77 | gg_pubdir50_add(request, GG_PUBDIR50_GENDER, GG_PUBDIR50_GENDER_SET_MALE);
78 |
79 | gg_pubdir50(session, request);
80 |
81 | gg_pubdir50_free(request);
82 | }
83 |
84 | expect data (14 00 00 00, auto, 01, xx xx xx xx, "firstname" 00, "Jan" 00, "gender" 00, "1" 00)
85 |
86 | #-----------------------------------------------------------------------------
87 |
88 | call {
89 | gg_pubdir50_t request;
90 |
91 | if (!(request = gg_pubdir50_new(GG_PUBDIR50_WRITE)))
92 | return;
93 |
94 | gg_pubdir50_add(request, GG_PUBDIR50_FIRSTNAME, "Anna");
95 | gg_pubdir50_add(request, GG_PUBDIR50_GENDER, GG_PUBDIR50_GENDER_SET_FEMALE);
96 |
97 | gg_pubdir50(session, request);
98 |
99 | gg_pubdir50_free(request);
100 | }
101 |
102 | expect data (14 00 00 00, auto, 01, xx xx xx xx, "firstname" 00, "Anna" 00, "gender" 00, "2" 00)
103 |
104 | #-----------------------------------------------------------------------------
105 | # Search reply
106 | #-----------------------------------------------------------------------------
107 |
108 | send (0e 00 00 00, auto, 05, 78 56 34 12, "FmNumber" 00, "123456" 00, "firstname" 00, "Jan" 00, "nickname" 00, "Janko" 20 "Muzykant" 00, "birthyear" 00, "1901" 00, "city" 00, "Warszawa" 00, "FmStatus" 00, "4" 00, 00, "FmNumber" 00, "234567" 00, "firstname" 00, "Adam" 00, "nickname" 00, "Nowy" 00, "birthyear" 00, "1979" 00, "city" 00, "Tuchola" 00, "FmStatus" 00, "1" 00, 00, "nextstart" 00, "345678" 00)
109 |
110 | expect event GG_EVENT_PUBDIR50_SEARCH_REPLY {
111 | struct {
112 | int num;
113 | const char *key;
114 | const char *value;
115 | } data[] = {
116 | { 0, GG_PUBDIR50_UIN, "123456" },
117 | { 0, GG_PUBDIR50_FIRSTNAME, "Jan" },
118 | { 0, GG_PUBDIR50_NICKNAME, "Janko Muzykant" },
119 | { 0, GG_PUBDIR50_BIRTHYEAR, "1901" },
120 | { 0, GG_PUBDIR50_CITY, "Warszawa" },
121 | { 0, GG_PUBDIR50_STATUS, "4" },
122 | { 1, GG_PUBDIR50_UIN, "234567" },
123 | { 1, GG_PUBDIR50_FIRSTNAME, "Adam" },
124 | { 1, GG_PUBDIR50_NICKNAME, "Nowy" },
125 | { 1, GG_PUBDIR50_BIRTHYEAR, "1979" },
126 | { 1, GG_PUBDIR50_CITY, "Tuchola" },
127 | { 1, GG_PUBDIR50_STATUS, "1" },
128 | };
129 | size_t i;
130 |
131 | if (gg_pubdir50_count(event->pubdir50) != 2)
132 | return FALSE;
133 |
134 | if (gg_pubdir50_seq(event->pubdir50) != 0x12345678)
135 | return FALSE;
136 |
137 | if (gg_pubdir50_type(event->pubdir50) != GG_PUBDIR50_SEARCH_REPLY)
138 | return FALSE;
139 |
140 | for (i = 0; i < sizeof(data) / sizeof(data[0]); i++) {
141 | if (strcmp(gg_pubdir50_get(event->pubdir50, data[i].num, data[i].key), data[i].value) != 0)
142 | return FALSE;
143 | }
144 |
145 | if (gg_pubdir50_get(event->pubdir50, 0, GG_PUBDIR50_LASTNAME) != NULL)
146 | return FALSE;
147 |
148 | if (gg_pubdir50_get(event->pubdir50, 2, GG_PUBDIR50_UIN) != NULL)
149 | return FALSE;
150 |
151 | if (gg_pubdir50_next(event->pubdir50) != 345678)
152 | return FALSE;
153 |
154 | return TRUE;
155 | }
156 |
157 |
--------------------------------------------------------------------------------
/test/manual/lib/xml.c:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2008 Wojtek Kaniewski
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License Version
6 | * 2.1 as published by the Free Software Foundation.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU Lesser General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU Lesser General Public
14 | * License along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
16 | * USA.
17 | */
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 |
24 | #include "xml.h"
25 |
26 | enum {
27 | ELEMENT_INVALID = -1, /**< Nieprawidłowy XML, nie parsujemy */
28 | ELEMENT_NONE = 0, /**< Brak lub nieznany, ignorowany element */
29 | ELEMENT_TOKEN, /**< */
30 | ELEMENT_TOKEN_SECRET, /**< */
31 | ELEMENT_TOKEN_EXPIRES_IN, /**< */
32 | ELEMENT_ERRORMSG, /**< */
33 | ELEMENT_STATUS, /**< */
34 | };
35 |
36 | struct parser_state {
37 | int depth; /**< Poziom zagnieżdżenia tagów */
38 | int element; /**< Typ aktualnego elementu */
39 | char *token; /**< Zawartość lub NULL */
40 | char *token_secret; /**< Zawartość lub NULL */
41 | char *error_msg; /**< Zawartość lub NULL */
42 | int status; /**< Zawartość lub -1 */
43 | int token_expires_in; /**< Zawartość lub -1 */
44 | };
45 |
46 | static void handle_start_element(void *data, const char *elem, const char **attr)
47 | {
48 | struct parser_state *state = data;
49 |
50 | if (state->element == ELEMENT_INVALID)
51 | return;
52 |
53 | state->depth++;
54 |
55 | if (state->depth == 1 && strcmp(elem, "result") != 0)
56 | state->element = ELEMENT_INVALID;
57 | else if (state->depth == 2 && strcmp(elem, "status") == 0)
58 | state->element = ELEMENT_STATUS;
59 | else if (state->depth == 2 && strcmp(elem, "oauth_token") == 0)
60 | state->element = ELEMENT_TOKEN;
61 | else if (state->depth == 2 && strcmp(elem, "oauth_token_secret") == 0)
62 | state->element = ELEMENT_TOKEN_SECRET;
63 | else if (state->depth == 2 && strcmp(elem, "oauth_token_expires_in") == 0)
64 | state->element = ELEMENT_TOKEN_EXPIRES_IN;
65 | else if (state->depth == 2 && strcmp(elem, "errorMsg") == 0)
66 | state->element = ELEMENT_ERRORMSG;
67 | else
68 | state->element = ELEMENT_NONE;
69 | }
70 |
71 | static void handle_end_element(void *data, const char *elem)
72 | {
73 | struct parser_state *state = data;
74 |
75 | if (state->element == ELEMENT_INVALID)
76 | return;
77 |
78 | state->depth--;
79 | state->element = ELEMENT_NONE;
80 | }
81 |
82 | static void handle_cdata(void *data, const char *str, int len)
83 | {
84 | struct parser_state *state = data;
85 | char *tmp;
86 |
87 | if (state->element == ELEMENT_INVALID || state->element == ELEMENT_NONE)
88 | return;
89 |
90 | tmp = malloc(len + 1);
91 |
92 | if (tmp == NULL)
93 | return;
94 |
95 | memcpy(tmp, str, len);
96 | tmp[len] = 0;
97 |
98 | switch (state->element) {
99 | case ELEMENT_STATUS:
100 | state->status = atoi(tmp);
101 | free(tmp);
102 | break;
103 | case ELEMENT_TOKEN:
104 | free(state->token);
105 | state->token = tmp;
106 | break;
107 | case ELEMENT_TOKEN_SECRET:
108 | free(state->token_secret);
109 | state->token_secret = tmp;
110 | break;
111 | case ELEMENT_TOKEN_EXPIRES_IN:
112 | state->token_expires_in = atoi(tmp);
113 | free(tmp);
114 | break;
115 | case ELEMENT_ERRORMSG:
116 | free(state->error_msg);
117 | state->error_msg = tmp;
118 | break;
119 | default:
120 | free(tmp);
121 | }
122 | }
123 |
124 | int gg_parse_token_reply(const char *reply, char **token, char **token_secret)
125 | {
126 | XML_Parser parser;
127 | struct parser_state state;
128 |
129 | memset(&state, 0, sizeof(state));
130 | state.status = -1;
131 | state.token_expires_in = -1;
132 |
133 | parser = XML_ParserCreate(NULL);
134 |
135 | if (parser == NULL)
136 | return -1;
137 |
138 | XML_SetUserData(parser, &state);
139 |
140 | XML_SetElementHandler(parser, handle_start_element, handle_end_element);
141 | XML_SetCharacterDataHandler(parser, handle_cdata);
142 |
143 | if (!XML_Parse(parser, reply, strlen(reply), 1)) {
144 | XML_ParserFree(parser);
145 | free(state.token);
146 | free(state.token_secret);
147 | free(state.error_msg);
148 | return -1;
149 | }
150 |
151 | XML_ParserFree(parser);
152 |
153 | if (state.element == ELEMENT_INVALID || state.status !=0 || state.token == NULL || state.token_secret == NULL) {
154 | free(state.token);
155 | free(state.token_secret);
156 | free(state.error_msg);
157 | return -1;
158 | }
159 |
160 | if (token)
161 | *token = state.token;
162 | else
163 | free(state.token);
164 |
165 | if (token_secret)
166 | *token_secret = state.token_secret;
167 | else
168 | free(state.token_secret);
169 |
170 | free(state.error_msg);
171 |
172 | return 0;
173 | }
174 |
175 | #ifdef STANDALONE
176 |
177 | int main(void)
178 | {
179 | const char *test = ""
180 | "c795432d623c3ec75137f50f66852b93"
181 | "9de77905611fb965e3023e1ffbbfad3e"
182 | "0";
183 | char *token;
184 | char *token_secret;
185 |
186 | if (parse_token_reply(test, strlen(test), &token, &token_secret) == -1) {
187 | printf("error\n");
188 | return 1;
189 | }
190 |
191 | printf("token = %s\ntoken_secret = %s\n", token, token_secret);
192 |
193 | return 0;
194 | }
195 |
196 | #endif
197 |
--------------------------------------------------------------------------------
/test/manual/search.c:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2008 Wojtek Kaniewski
3 | *
4 | * This program is free software; you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License Version
6 | * 2.1 as published by the Free Software Foundation.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU Lesser General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU Lesser General Public
14 | * License along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
16 | * USA.
17 | */
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | #include "lib/oauth.h"
26 | #include "lib/http.h"
27 | #include "lib/xml.h"
28 | #include "lib/urlencode.h"
29 |
30 | #include "network.h"
31 |
32 | char *token, *token_secret;
33 |
34 | char *config_uin = NULL;
35 | char *config_password = NULL;
36 |
37 | static int config_read(void)
38 | {
39 | char buf[256];
40 | FILE *f;
41 |
42 | if (!(f = fopen("config", "r"))) {
43 | if (!(f = fopen("../config", "r")))
44 | return -1;
45 | }
46 |
47 | while (fgets(buf, sizeof(buf), f)) {
48 | while (strlen(buf) > 0 && isspace(buf[strlen(buf) - 1]))
49 | buf[strlen(buf) - 1] = 0;
50 |
51 | if (!strncmp(buf, "uin ", 4)) {
52 | free(config_uin);
53 | config_uin = strdup(buf + 4);
54 | }
55 |
56 | if (!strncmp(buf, "password ", 9)) {
57 | free(config_password);
58 | config_password = strdup(buf + 9);
59 | }
60 | }
61 |
62 | fclose(f);
63 |
64 | if (!config_uin || !config_password)
65 | return -1;
66 |
67 | return 0;
68 | }
69 |
70 | static void config_free(void)
71 | {
72 | free(config_uin);
73 | free(config_password);
74 | }
75 |
76 | #define HTTP_METHOD1 "POST"
77 | #define HTTP_URL1 "http://api.gadu-gadu.pl/request_token"
78 | static int oauth_request(void)
79 | {
80 | char *auth, *reply;
81 |
82 | printf("\033[1m/request_token\033[0m\n\n");
83 |
84 | if (!(auth = gg_oauth_generate_header(HTTP_METHOD1, HTTP_URL1, config_uin, config_password, NULL, NULL)))
85 | return 0;
86 |
87 | printf("header = '%s'\n", auth);
88 |
89 | reply = gg_http_fetch(HTTP_METHOD1, HTTP_URL1, auth, NULL);
90 |
91 | free(auth);
92 |
93 | if (reply == NULL)
94 | return 0;
95 |
96 | printf("reply = '%s'\n", reply);
97 |
98 | if (gg_parse_token_reply(reply, &token, &token_secret) == -1) {
99 | free(reply);
100 | return 0;
101 | }
102 |
103 | free(reply);
104 |
105 | printf("token = '%s'\ntoken_secret = '%s'\n", token, token_secret);
106 | return 1;
107 | }
108 |
109 | #define HTTP_AUTH_METHOD "POST"
110 | #define HTTP_AUTH_URL "https://login.gadu-gadu.pl/authorize"
111 | static int oauth_authorize(void)
112 | {
113 | char *tmp, *reply;
114 |
115 | printf("\n\033[1m/authorize\033[0m\n\n");
116 |
117 | tmp = gg_urlencode_printf("callback_url=http://www.mojageneracja.pl&request_token=%s&uin=%s&password=%s",
118 | token, config_uin, config_password);
119 |
120 | reply = gg_http_fetch(HTTP_AUTH_METHOD, HTTP_AUTH_URL, NULL, tmp);
121 |
122 | free(reply);
123 | free(tmp);
124 | return 1;
125 | }
126 |
127 | #define HTTP_METHOD2 "POST"
128 | #define HTTP_URL2 "http://api.gadu-gadu.pl/access_token"
129 | static int oauth_access(void)
130 | {
131 | char *auth, *reply;
132 | printf("\n\033[1m/access_token\033[0m\n\n");
133 |
134 | if (!(auth = gg_oauth_generate_header(HTTP_METHOD2, HTTP_URL2,
135 | config_uin, config_password, token, token_secret)))
136 | {
137 | return 0;
138 | }
139 |
140 | printf("header = '%s'\n", auth);
141 |
142 | reply = gg_http_fetch(HTTP_METHOD2, HTTP_URL2, auth, NULL);
143 |
144 | free(auth);
145 |
146 | if (reply == NULL)
147 | return 0;
148 |
149 | free(token); token = NULL;
150 | free(token_secret); token_secret = NULL;
151 |
152 | if (gg_parse_token_reply(reply, &token, &token_secret) == -1) {
153 | free(reply);
154 | return 0;
155 | }
156 |
157 | printf("reply = '%s'\n", reply);
158 |
159 | free(reply);
160 | return 1;
161 | }
162 |
163 | static int oauth_init(void)
164 | {
165 | if (!oauth_request())
166 | return 0;
167 | if (!oauth_authorize())
168 | return 0;
169 | if (!oauth_access())
170 | return 0;
171 | return 1;
172 | }
173 |
174 | #define HTTP_METHOD3 "GET"
175 | #define HTTP_URL3_BASE "http://api.gadu-gadu.pl/users/"
176 |
177 | static void oauth_ask(const char *uid)
178 | {
179 | char *auth;
180 | char *reply;
181 | char *tmp;
182 |
183 | tmp = gg_urlencode_printf(HTTP_URL3_BASE "%s.xml", uid);
184 |
185 | printf("\n\033[1m%s\033[0m\n\n", tmp);
186 |
187 | auth = gg_oauth_generate_header(HTTP_METHOD3, tmp, config_uin, config_password, token, token_secret);
188 |
189 | if (auth == NULL) {
190 | free(tmp);
191 | return;
192 | }
193 |
194 | printf("header = '%s'\n", auth);
195 |
196 | reply = gg_http_fetch(HTTP_METHOD3, tmp, auth, NULL);
197 |
198 | if (reply == NULL)
199 | return;
200 |
201 | printf("reply = '%s'\n", reply);
202 |
203 | free(reply);
204 | free(auth);
205 | free(tmp);
206 | }
207 |
208 | int main(int argc, char **argv)
209 | {
210 | int i;
211 |
212 | #ifdef _WIN32
213 | gg_win32_init_network();
214 | #endif
215 |
216 | http_init();
217 |
218 | if (argc < 2) {
219 | printf("usage: %s [uid2] [uid3] [uid4] ....\n", argv[0]);
220 | return 1;
221 | }
222 |
223 | if (config_read() == -1) {
224 | perror("config");
225 | exit(1);
226 | }
227 |
228 | if (!oauth_init()) {
229 | free(token);
230 | free(token_secret);
231 | config_free();
232 | return 1;
233 | }
234 |
235 | for (i = 1; i < argc; i++) /* mozeby wypadalo sprawdzac przez strtol() czy to faktycznie jest int? */
236 | oauth_ask(argv[i]);
237 |
238 | config_free();
239 | free(token);
240 | free(token_secret);
241 | return 0;
242 | }
243 |
--------------------------------------------------------------------------------