├── test ├── Makefile.am ├── manual │ ├── search.txt │ ├── lib │ │ ├── Makefile.am │ │ ├── base64.h │ │ ├── xml.h │ │ ├── hmac.h │ │ ├── http.h │ │ ├── oauth.h │ │ ├── urlencode.h │ │ ├── oauth_parameter.h │ │ ├── sha1.h │ │ ├── http.c │ │ ├── oauth_parameter.c │ │ ├── urlencode.c │ │ ├── hmac.c │ │ ├── base64.c │ │ └── xml.c │ ├── userconfig.h │ ├── Makefile.am │ ├── userconfig.c │ ├── userlist.c │ └── search.c ├── automatic │ ├── script │ │ ├── Makefile.am │ │ ├── 99-logoff.scr │ │ ├── 90-xml.scr │ │ ├── 95-ping.scr │ │ ├── script.h │ │ ├── 05-multilogon.scr │ │ ├── 00-login.scr │ │ ├── 30-status.scr │ │ ├── 12-user_data.scr │ │ ├── 40-userlist.scr │ │ ├── 25-images.scr │ │ └── 50-pubdir.scr │ ├── wine-wrapper.sh │ ├── message1.c │ ├── connect.txt │ ├── endian1.c │ ├── Makefile.am │ ├── connect.pem │ ├── protocol.txt │ └── hash.c ├── config.sample └── valgrind ├── NEWS ├── pkgconfig ├── Makefile.am └── libgadu.pc.in ├── ChangeLog ├── include ├── Makefile.am ├── deflate.h ├── debug.h ├── resolver.h ├── encoding.h ├── strman.h ├── fileio.h ├── message.h ├── tvbuilder.h ├── tvbuff.h ├── session.h ├── protobuf.h └── network.h ├── examples ├── Makefile.am ├── status.c ├── httphash.c ├── send.c ├── register.c ├── remind.c ├── conn-async.c └── token.c ├── declspec.sh ├── Makefile.am ├── autogen.sh ├── docs ├── proxy.dox ├── groups.dox ├── Makefile.am ├── todo.dox ├── re.dox ├── contacts.dox ├── token.dox ├── status.dox ├── importexport.dox ├── http.dox ├── build.dox ├── mainpage.dox ├── dcc7.dox └── pubdir50.dox ├── m4 ├── stdint.m4 └── openssl.m4 ├── autoclean.sh ├── .gitignore ├── src ├── Makefile.am ├── endian.c ├── libgadu.sym.in ├── protobuf.c └── protobuf-c.c.patch ├── protobufgen.sh ├── AUTHORS ├── README.md ├── README.en └── README /test/Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = automatic manual 2 | EXTRA_DIST = config.sample 3 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | Informacje o nowościach znajdują się na stronie http://toxygen.net/libgadu/ 2 | -------------------------------------------------------------------------------- /pkgconfig/Makefile.am: -------------------------------------------------------------------------------- 1 | pkgconfigdir = $(libdir)/pkgconfig 2 | pkgconfig_DATA = libgadu.pc 3 | -------------------------------------------------------------------------------- /test/manual/search.txt: -------------------------------------------------------------------------------- 1 | - Skopiowac funkcje do libgadu, linkowac sie z libgadu i korzystac z nich. 2 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | Lista zmian w kodzie źródłowym: 2 | https://github.com/wojtekka/libgadu/commits/master 3 | 4 | Lista zmian w interfejsie biblioteki: 5 | http://libgadu.net/docs/group__changelog.html 6 | -------------------------------------------------------------------------------- /include/Makefile.am: -------------------------------------------------------------------------------- 1 | nodist_include_HEADERS = libgadu.h 2 | noinst_HEADERS = debug.h deflate.h encoding.h fileio.h internal.h message.h network.h packets.pb-c.h protobuf.h protobuf-c.h protocol.h resolver.h session.h strman.h tvbuff.h tvbuilder.h 3 | 4 | packets.pb-c.h: ../packets.proto 5 | cd $(top_builddir) ; sh protobufgen.sh 6 | -------------------------------------------------------------------------------- /examples/Makefile.am: -------------------------------------------------------------------------------- 1 | noinst_PROGRAMS = send httphash conn-async status 2 | LDADD = $(top_builddir)/src/libgadu.la 3 | AM_LDFLAGS = @LDFLAGS_NO_INSTALL@ 4 | EXTRA_DIST = register.c remind.c token.c 5 | 6 | #necessary for network.h file 7 | AM_CFLAGS = -I$(top_srcdir)/include 8 | 9 | httphash_CFLAGS = -DGG_IGNORE_DEPRECATED 10 | -------------------------------------------------------------------------------- /pkgconfig/libgadu.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: libgadu 7 | Version: @VERSION@ 8 | Description: libgadu 9 | Requires.private: @REQUIRES_PRIVATE@ 10 | Libs: -L${libdir} -lgadu 11 | Libs.private: @LIBS_PRIVATE@ 12 | Cflags: -I${includedir} 13 | 14 | -------------------------------------------------------------------------------- /test/manual/lib/Makefile.am: -------------------------------------------------------------------------------- 1 | if HAVE_CURL_AND_EXPAT 2 | noinst_LIBRARIES = libsearch.a 3 | endif 4 | 5 | AM_CPPFLAGS = -DGG_IGNORE_DEPRECATED -I$(top_srcdir)/include 6 | 7 | libsearch_a_SOURCES = base64.c base64.h hmac.c hmac.h http.c http.h oauth.c oauth.h oauth_parameter.c oauth_parameter.h sha1.c sha1.h urlencode.c urlencode.h xml.c xml.h 8 | -------------------------------------------------------------------------------- /test/automatic/script/Makefile.am: -------------------------------------------------------------------------------- 1 | EXTRA_DIST = \ 2 | 00-login.scr \ 3 | 05-multilogon.scr \ 4 | 10-contacts.scr \ 5 | 12-user_data.scr \ 6 | 20-messages.scr \ 7 | 25-images.scr \ 8 | 30-status.scr \ 9 | 40-userlist.scr \ 10 | 50-pubdir.scr \ 11 | 90-xml.scr \ 12 | 95-ping.scr \ 13 | 99-logoff.scr 14 | noinst_HEADERS = script.h 15 | -------------------------------------------------------------------------------- /declspec.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # this script if for converting libgadu.h file to be used with MSVC 4 | 5 | cat $1 \ 6 | | sed -e "s/^[a-z][a-z0-9_ *]\+gg_[a-z0-9_]\+(.*/__declspec(dllimport) \0/g"\ 7 | | sed -e "s/^extern [a-z][a-z0-9_ *]\+gg_[a-z0-9_]\+;.*/__declspec(dllimport) \0/g"\ 8 | | sed -e "s/^extern [a-z][a-z0-9_ *]\+(\*gg_[a-z0-9_]\+)(.*/__declspec(dllimport) \0/g" 9 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = include src pkgconfig examples @SUBDIRS_DOXYGEN@ 2 | if ENABLE_TESTS 3 | SUBDIRS += test 4 | endif 5 | 6 | DIST_SUBDIRS = include src pkgconfig examples docs test 7 | 8 | EXTRA_DIST = packets.proto protobufgen.sh autogen.sh 9 | 10 | LIBTOOL_DEPS = @LIBTOOL_DEPS@ 11 | 12 | libtool: $(LIBTOOL_DEPS) 13 | $(SHELL) ./config.status --recheck 14 | 15 | ACLOCAL_AMFLAGS = -I m4 16 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo protobuf && ./protobufgen.sh || exit 1 4 | echo aclocal && aclocal -I m4 || exit 1 5 | echo autoheader && autoheader || exit 1 6 | echo libtoolize && libtoolize --copy || exit 1 7 | echo automake && automake --add-missing --copy --foreign || exit 1 8 | echo autoconf && autoconf || exit 1 9 | 10 | if test x$NOCONFIGURE = x ; then 11 | echo configure 12 | ./configure $* 13 | fi 14 | 15 | -------------------------------------------------------------------------------- /test/automatic/wine-wrapper.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # it strips quotes, but for this purpose it's not a problem 4 | 5 | newcmd="" 6 | for param in "$@" ; do 7 | newcmd="${newcmd}${param} " 8 | if [ "$param" == "--" ]; then 9 | newcmd="${newcmd}wine " 10 | fi 11 | done 12 | $newcmd 13 | 14 | # bug: _mktemp_s run on wine creates 0444 chmoded file, 15 | # so it can't remove temp files by itself 16 | rm -rf hashdata.* 17 | -------------------------------------------------------------------------------- /test/config.sample: -------------------------------------------------------------------------------- 1 | # Test account number 2 | uin 12345678 3 | 4 | # Test account password 5 | password test 6 | 7 | # Public IP 8 | #ip 192.168.0.123 9 | 10 | # Public port 11 | #port 1550 12 | 13 | # Peer account number 14 | peer 23456789 15 | 16 | # Test file 17 | #file /tmp/test.bin 18 | 19 | # Test file size 20 | #size 1048576 21 | 22 | # Received files directory (must exist, will overwrite without asking!) 23 | #dir /tmp 24 | -------------------------------------------------------------------------------- /test/automatic/script/99-logoff.scr: -------------------------------------------------------------------------------- 1 | #----------------------------------------------------------------------------- 2 | # Disconnecting 3 | #----------------------------------------------------------------------------- 4 | 5 | send (0b 00 00 00, auto) 6 | 7 | expect event GG_EVENT_DISCONNECT 8 | 9 | #----------------------------------------------------------------------------- 10 | # Logging off 11 | #----------------------------------------------------------------------------- 12 | 13 | logoff 14 | expect disconnect 15 | -------------------------------------------------------------------------------- /test/automatic/script/90-xml.scr: -------------------------------------------------------------------------------- 1 | #----------------------------------------------------------------------------- 2 | # XML event 3 | #----------------------------------------------------------------------------- 4 | 5 | send (27 00 00 00, auto, "" 0d 0a) 6 | 7 | expect event GG_EVENT_XML_EVENT ( 8 | xml_event.data == "\r\n" 9 | ) 10 | 11 | send (2c 00 00 00, auto, "" 0d 0a) 12 | 13 | expect event GG_EVENT_XML_EVENT ( 14 | xml_event.data == "\r\n" 15 | ) 16 | 17 | -------------------------------------------------------------------------------- /test/automatic/script/95-ping.scr: -------------------------------------------------------------------------------- 1 | #----------------------------------------------------------------------------- 2 | # Ping 3 | #----------------------------------------------------------------------------- 4 | 5 | call { 6 | gg_ping(session); 7 | } 8 | 9 | expect data (08 00 00 00, auto) 10 | 11 | #----------------------------------------------------------------------------- 12 | # Pong 13 | #----------------------------------------------------------------------------- 14 | 15 | send (07 00 00 00, auto) 16 | 17 | expect event GG_EVENT_PONG 18 | -------------------------------------------------------------------------------- /docs/proxy.dox: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | \defgroup proxy Serwer pośredniczący 4 | \ingroup misc 5 | 6 | \details 7 | 8 | Biblioteka \e libgadu obsługuje wykonywanie połączeń za pomocą serwerów 9 | pośredniczących HTTP. Możliwe jest użycie serwerów wymagających autoryzacji 10 | mechanizmem podstawowym (Digest i NTLM nie są obsługiwane). Aby wymusić 11 | korzystanie z serwera pośredniczącego, należy ustawić flagę \c gg_proxy_enabled 12 | i odpowiednio ustawić poszczególne zmienne. 13 | 14 | \bug Serwer pośredniczący nie jest wykorzystywany dla połączeń bezpośrednich. 15 | 16 | \bug Ustawienia serwera pośredniczącego są globalne dla wszystkich połączeń. 17 | 18 | */ 19 | -------------------------------------------------------------------------------- /docs/groups.dox: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | \defgroup session Połączenie z serwerem 4 | 5 | \defgroup chat Konferencje 6 | \ingroup session 7 | 8 | \defgroup dcc Połączenia bezpośrednie między klientami 9 | 10 | \defgroup services Usługi dodatkowe 11 | 12 | \defgroup debug Odpluskwianie 13 | \ingroup misc 14 | 15 | \defgroup helper Funkcje pomocnicze 16 | \ingroup misc 17 | 18 | \defgroup misc Pozostałe funkcje 19 | 20 | \defgroup ip Konfiguracja IP 21 | \ingroup misc 22 | \bug Ustawienia są globalne dla wszystkich połączeń. 23 | 24 | \defgroup socketmanager Własne funkcje do nawiązywania połączeń TCP/TLS 25 | \ingroup misc 26 | 27 | \defgroup version Informacje o bibliotece 28 | \ingroup misc 29 | 30 | */ 31 | -------------------------------------------------------------------------------- /docs/Makefile.am: -------------------------------------------------------------------------------- 1 | EXTRA_DIST = \ 2 | Doxyfile \ 3 | protocol.html \ 4 | build.dox \ 5 | changelog.dox \ 6 | contacts.dox \ 7 | dcc6.dox \ 8 | dcc7.dox \ 9 | events.dox \ 10 | groups.dox \ 11 | http.dox \ 12 | importexport.dox \ 13 | login.dox \ 14 | mainpage.dox \ 15 | messages.dox \ 16 | proxy.dox \ 17 | pubdir50.dox \ 18 | re.dox \ 19 | status.dox \ 20 | todo.dox \ 21 | token.dox 22 | 23 | all-local: html-stamp 24 | 25 | html-stamp: $(top_builddir)/include/libgadu.h $(wildcard $(top_srcdir)/include/*.h) $(wildcard $(top_srcdir)/src/*.c) $(wildcard $(srcdir)/*.dox) 26 | rm -rf $(DOXYFILE_HTML_DIR) 27 | $(DOXYGEN) 28 | touch html-stamp 29 | 30 | clean-local: 31 | rm -rf $(DOXYFILE_HTML_DIR) html-stamp 32 | -------------------------------------------------------------------------------- /docs/todo.dox: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | \defgroup todo Brakująca funkcjonalność 4 | 5 | \details 6 | 7 | Ze względu na konieczność użycia \ref re "inżynierii wstecznej", biblioteka 8 | nie gwarantuje stuprocentowej zgodności z oryginalnym klientem. Poza tym, 9 | część funkcjonalności z braku czasu, zasobów lub zainteresowania nie 10 | została jeszcze zaimplementowana: 11 | 12 | - przesyłanie plików przez serwer w Gadu-Gadu 7.x, 13 | - bezpośrednie połączenia głosowe w Gadu-Gadu 7.x, 14 | - statusy zawierające czas powrotu, 15 | - konfiguracja adresów IP i serwerów pośredniczących dla każdego połączenia 16 | osobno. 17 | 18 | Jeśli jesteś w stanie pomóc, skontaktuj się z autorami na liście dyskusyjnej 19 | libgadu-devel. 20 | 21 | */ 22 | 23 | -------------------------------------------------------------------------------- /m4/stdint.m4: -------------------------------------------------------------------------------- 1 | dnl Based on AC_NEED_STDINT_H by Guido Draheim that can be 2 | dnl found at http://www.gnu.org/software/ac-archive/. Do not complain him 3 | dnl about this macro. 4 | 5 | AC_DEFUN([AC_NEED_STDINT_H], 6 | [AC_MSG_CHECKING([for uintXX_t types]) 7 | 8 | ac_header_stdint="" 9 | dnl inttypes have PRIu64 defined, stdint.h does not 10 | for i in inttypes.h stdint.h sys/inttypes.h sys/int_types.h sys/types.h; do 11 | if test "x$ac_header_stdint" = "x"; then 12 | AC_TRY_COMPILE([#include <$i>], [uint32_t foo], [ac_header_stdint=$i]) 13 | fi 14 | done 15 | 16 | if test "x$ac_header_stdint" != "x" ; then 17 | AC_MSG_RESULT([found in <$ac_header_stdint>]) 18 | STDINT_H="$ac_header_stdint" 19 | else 20 | AC_MSG_RESULT([not found, using reasonable defaults]) 21 | STDINT_H="" 22 | fi 23 | ]) 24 | -------------------------------------------------------------------------------- /autoclean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | rm -rf \ 4 | aclocal.m4 \ 5 | autom4te.cache \ 6 | compile \ 7 | confdefs.h \ 8 | config.* \ 9 | configure \ 10 | depcomp \ 11 | install-sh \ 12 | INSTALL \ 13 | libtool \ 14 | ltconfig \ 15 | ltmain.sh \ 16 | m4/lt*.m4 \ 17 | m4/libtool.m4 \ 18 | Makefile \ 19 | Makefile.in \ 20 | missing \ 21 | mkinstalldirs \ 22 | stamp* \ 23 | stdint.h \ 24 | src/Makefile \ 25 | src/Makefile.in \ 26 | src/.deps \ 27 | src/.libs \ 28 | src/*.o \ 29 | src/*.lo \ 30 | src/*.la \ 31 | include/Makefile \ 32 | include/Makefile.in \ 33 | include/libgadu.h \ 34 | include/stamp* \ 35 | docs/Makefile.in \ 36 | examples/Makefile.in \ 37 | test/Makefile.in \ 38 | test/*/Makefile.in \ 39 | test/*/*/Makefile.in \ 40 | pkgconfig/Makefile \ 41 | pkgconfig/Makefile.in \ 42 | pkgconfig/libgadu.pc \ 43 | pkgconfig/stamp* 44 | -------------------------------------------------------------------------------- /test/valgrind: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | PROGRAM_PATH=$(dirname "$0") 4 | PROGRAM_NAME=$(basename "$0" | sed 's/-\?valgrind$//') 5 | 6 | if [ -z "$PROGRAM_NAME" ]; then 7 | echo "Not to be run directly" 8 | exit 1 9 | fi 10 | 11 | PROGRAM="" 12 | for i in "$PROGRAM_PATH/.libs/$PROGRAM_NAME" "$PROGRAM_PATH/.libs/lt-$PROGRAM_NAME" "$PROGRAM_PATH/$PROGRAM_NAME"; do 13 | if [ -x "$i" ]; then 14 | PROGRAM=$i 15 | break 16 | fi 17 | done 18 | 19 | if [ -n "$PROGRAM" ]; then 20 | LOG_FILE="$PROGRAM_PATH/$PROGRAM_NAME-valgrind.log" 21 | LD_LIBRARY_PATH="$PROGRAM_PATH/../../src/.libs" valgrind \ 22 | --tool=memcheck --leak-check=full --show-reachable=yes --track-origins=yes \ 23 | --trace-children=yes --child-silent-after-fork=yes --track-fds=yes \ 24 | --log-file="$LOG_FILE" "$PROGRAM" $@ 25 | echo "valgrind output is in file \"$LOG_FILE\"" 26 | else 27 | echo "$PROGRAM_NAME not found" 28 | fi 29 | -------------------------------------------------------------------------------- /test/automatic/message1.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 | /* Tutaj będziemy testować "metody" "klasy" gg_message_t. */ 20 | 21 | int main(void) 22 | { 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /test/manual/lib/base64.h: -------------------------------------------------------------------------------- 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 | #ifndef BASE64_H 20 | #define BASE64_H 21 | 22 | char *gg_base64_encode2(const char *buf, ssize_t len); 23 | char *gg_base64_decode(const char *buf); 24 | 25 | #endif /* BASE64_H */ 26 | -------------------------------------------------------------------------------- /test/manual/lib/xml.h: -------------------------------------------------------------------------------- 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 | #ifndef XML_H 20 | #define XML_H 21 | 22 | #include 23 | 24 | int gg_parse_token_reply(const char *reply, char **token, char **token_secret); 25 | 26 | #endif /* XML_H */ 27 | -------------------------------------------------------------------------------- /test/manual/lib/hmac.h: -------------------------------------------------------------------------------- 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 | #ifndef HMAC_SHA1_H 20 | #define HMAC_SHA1_H 21 | 22 | void gg_hmac_sha1(unsigned char *text, int text_len, unsigned char *key, int key_len, unsigned char *digest); 23 | 24 | #endif /* HMAC_SHA1_H */ 25 | -------------------------------------------------------------------------------- /test/manual/lib/http.h: -------------------------------------------------------------------------------- 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 | #ifndef HTTP_H 20 | #define HTTP_H 21 | 22 | char *gg_http_fetch(const char *method, const char *url, const char *auth_header, char *post_data); 23 | void http_init(void); 24 | 25 | #endif /* HTTP_H */ 26 | -------------------------------------------------------------------------------- /docs/re.dox: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | \defgroup re Użycie inżynierii wstecznej 4 | \details 5 | 6 | \e arturs w wątku A jak z legalnoscia tego? na 7thguard.net napisał: 7 | 8 |
> > > ... jak wyzej.  
 9 | > >  
10 | > > niby co i dlaczego miałoby być nielegalne?  
11 | > >  
12 | >  
13 | > Wykorzystywanie zamknietego protokolu, opracowanego przez  
14 | > firme komercyjna.  
15 | > Wydaje mi sie, ze moga miec prawo do tego, by zachowac go w  
16 | > tajemnicy.  
17 |        
18 | Well, nie maja. To, co zrobili ludzie tworzacy linuksowe odpowiedniki
19 | (podobnie jak w przypadku windows/samby, napstera/klonów itd. itp.) to
20 | typowy przyklad reverse engineering for interoperability (w przypadku
21 | Polski - art. 75 ust. 2 pkt 3 ustawy o p.a. - spelnione sa wszystkie
22 | warunki z podpunktow a, b i c).
23 | 24 | \warning Mimo braku zastrzeżeń prawnych, należy pamiętać, że używanie 25 | alternatywnych klientów jest niezgodne z regulaminem korzystania 26 | z serwisu Gadu-Gadu. 27 | 28 | */ 29 | 30 | -------------------------------------------------------------------------------- /test/manual/lib/oauth.h: -------------------------------------------------------------------------------- 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 | #ifndef OAUTH_H 20 | #define OAUTH_H 21 | 22 | char *gg_oauth_generate_header(const char *method, const char *url, 23 | const char *consumer_key, const char *consumer_secret, 24 | const char *token, const char *token_secret); 25 | 26 | #endif /* OAUTH_H */ 27 | -------------------------------------------------------------------------------- /include/deflate.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 | #ifndef LIBGADU_DEFLATE_H 20 | #define LIBGADU_DEFLATE_H 21 | 22 | #include "libgadu.h" 23 | 24 | unsigned char *gg_deflate(const char *in, size_t *out_lenp); 25 | char *gg_inflate(const unsigned char *in, size_t length); 26 | 27 | #endif /* LIBGADU_DEFLATE_H */ 28 | -------------------------------------------------------------------------------- /include/debug.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_DEBUG_H 20 | #define LIBGADU_DEBUG_H 21 | 22 | #include "libgadu.h" 23 | 24 | void gg_debug_dump(struct gg_session *sess, int level, const char *buf, size_t len); 25 | void gg_debug_common(struct gg_session *sess, int level, const char *format, va_list ap); 26 | 27 | #endif /* LIBGADU_DEBUG_H */ 28 | -------------------------------------------------------------------------------- /include/resolver.h: -------------------------------------------------------------------------------- 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 | #ifndef LIBGADU_RESOLVER_H 20 | #define LIBGADU_RESOLVER_H 21 | 22 | #include "network.h" 23 | 24 | int gg_gethostbyname_real(const char *hostname, struct in_addr **result, unsigned int *count, int pthread); 25 | int gg_resolver_recv(int fd, void *buf, size_t len); 26 | void gg_resolver_cleaner(void *data); 27 | 28 | #endif /* LIBGADU_RESOLVER_H */ 29 | -------------------------------------------------------------------------------- /include/encoding.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (C) Copyright 2008-2009 Jakub Zawadzki 3 | * Wojtek Kaniewski 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 | #ifndef LIBGADU_ENCODING_H 21 | #define LIBGADU_ENCODING_H 22 | 23 | #include "libgadu.h" 24 | 25 | char *gg_encoding_convert(const char *src, gg_encoding_t src_encoding, 26 | gg_encoding_t dst_encoding, int src_length, int dst_length); 27 | 28 | #endif /* LIBGADU_SESSION_H */ 29 | -------------------------------------------------------------------------------- /test/manual/lib/urlencode.h: -------------------------------------------------------------------------------- 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 | #ifndef URLENCODE_H 20 | #define URLENCODE_H 21 | 22 | #include 23 | #include 24 | 25 | size_t gg_urlencode_strlen(const char *s); 26 | char *gg_urlencode_strcpy(char *dest, const char *src); 27 | char *gg_urlencode(const char *s); 28 | char *gg_urlencode_printf(char *format, ...) GG_GNUC_PRINTF(1, 2); 29 | 30 | #endif /* URLENCODE_H */ 31 | -------------------------------------------------------------------------------- /test/manual/lib/oauth_parameter.h: -------------------------------------------------------------------------------- 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 | #ifndef OAUTH_PARAMETER_H 20 | #define OAUTH_PARAMETER_H 21 | 22 | typedef struct gg_oauth_parameter gg_oauth_parameter_t; 23 | 24 | int gg_oauth_parameter_set(gg_oauth_parameter_t **list, const char *key, const char *value); 25 | char *gg_oauth_parameter_join(gg_oauth_parameter_t *list, int header); 26 | void gg_oauth_parameter_free(gg_oauth_parameter_t *list); 27 | 28 | #endif /* OAUTH_PARAMETER_H */ 29 | -------------------------------------------------------------------------------- /docs/contacts.dox: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | \defgroup contacts Lista kontaktów 4 | \ingroup session 5 | 6 | \details 7 | 8 | Po udanym połączeniu z serwerem, pierwszą czynnością powinno być wysłanie 9 | listy kontaktów. W innym przypadku serwer nie wyśle żadnych zakolejkowanych 10 | wiadomości, ponieważ najprawdopodobniej filtry antyspamowe traktują inaczej 11 | wiadomości od znajomych i nieznajomych. Do wysłania listy kontaktów zaraz 12 | po udanym połączeniu, nawet gdyby była pusta, należy użyć funkcji 13 | \c gg_notify() lub \c gg_notify_ex(). Dodawanie i usuwanie kontaktów 14 | podczas połączenia można przeprowadzać za pomocą funkcji \c gg_add_notify(), 15 | \c gg_add_notify_ex(), \c gg_remove_notify() i \c gg_remove_notify_ex(). 16 | 17 | Przykład wysłania listy kontaktów składającej się z dwóch wpisów: 18 | 19 | \code 20 | uin_t kontakty[] = { 12345, 67890 }; 21 | 22 | // ... 23 | 24 | gg_notify(sesja, kontakty, 2); 25 | \endcode 26 | 27 | Przykład wysłania pustej listy kontaktów, by móc odbierać wiadomości: 28 | 29 | \code 30 | gg_notify(sesja, NULL, 0); 31 | \endcode 32 | 33 | Po wysłaniu listy kontaktów otrzymamy informacje o statusie znajomych 34 | (za pomocą \c GG_EVENT_NOTIFY, \c GG_EVENT_NOTIFY60 lub \c GG_EVENT_NOTIFY77) 35 | oraz informacje dodatkowe o kontaktach (za pomocą \c GG_EVENT_USER_DATA). 36 | 37 | */ 38 | -------------------------------------------------------------------------------- /test/manual/userconfig.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 USERCONFIG_H 20 | #define USERCONFIG_H 21 | 22 | extern unsigned int config_uin; 23 | extern char *config_password; 24 | extern unsigned int config_peer; 25 | extern char *config_file; 26 | extern char *config_dir; 27 | extern unsigned int config_size; 28 | extern unsigned long config_ip; 29 | extern unsigned int config_port; 30 | extern char *config_server; 31 | extern char *config_proxy; 32 | 33 | int config_read(void); 34 | void config_free(void); 35 | 36 | #endif /* USERCONFIG_H */ 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Makefile 2 | Makefile.in 3 | *.m4 4 | *.o 5 | *.la 6 | *.a 7 | *.lo 8 | *.exe 9 | .deps 10 | .libs 11 | *.tar.gz 12 | *.pb-c.* 13 | stamp-h* 14 | .dirstamp 15 | config.* 16 | clang_output_* 17 | autom4te.cache/ 18 | compile 19 | configure 20 | depcomp 21 | docs/html 22 | docs/Doxyfile 23 | docs/html-stamp 24 | pkgconfig/libgadu.pc 25 | include/libgadu.h 26 | src/libgadu.def* 27 | install-sh 28 | libtool 29 | ltmain.sh 30 | missing 31 | test-driver 32 | libgadu.sym 33 | libgadu-*/ 34 | examples/conn-async 35 | examples/httphash 36 | examples/register-async 37 | examples/register-sync 38 | examples/remind-async 39 | examples/remind-sync 40 | examples/send 41 | examples/status 42 | examples/token-async 43 | examples/token-sync 44 | examples/token.?????? 45 | test/config 46 | test/automatic/*.log 47 | test/automatic/*.trs 48 | test/automatic/connect 49 | test/automatic/convert 50 | test/automatic/endian1 51 | test/automatic/hash 52 | test/automatic/message1 53 | test/automatic/message2 54 | test/automatic/packet 55 | test/automatic/protocol 56 | test/automatic/resolver 57 | test/automatic/script.c 58 | test/automatic/skipped.c 59 | test/automatic/libgadu-*.c 60 | test/automatic/*-valgrind 61 | test/manual/client 62 | test/manual/dcc7 63 | test/manual/userlist 64 | test/manual/search 65 | test/manual/voice7 66 | test/manual/libgadu-*.c 67 | test/manual/*-valgrind 68 | -------------------------------------------------------------------------------- /test/manual/lib/sha1.h: -------------------------------------------------------------------------------- 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 | #ifndef SHA1_H 20 | #define SHA1_H 21 | 22 | #include "config.h" 23 | 24 | #ifdef HAVE_OPENSSL 25 | 26 | #include 27 | 28 | #else 29 | 30 | #include 31 | 32 | typedef struct { 33 | uint32_t state[5]; 34 | uint32_t count[2]; 35 | unsigned char buffer[64]; 36 | } SHA_CTX; 37 | 38 | void SHA1_Init(SHA_CTX* context); 39 | void SHA1_Update(SHA_CTX* context, const unsigned char* data, unsigned int len); 40 | void SHA1_Final(unsigned char digest[20], SHA_CTX* context); 41 | 42 | #endif /* HAVE_OPENSSL */ 43 | 44 | #endif /* SHA1_H */ 45 | -------------------------------------------------------------------------------- /docs/token.dox: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | \defgroup token Tokeny 4 | \ingroup services 5 | 6 | \details 7 | 8 | W celu zarejestrowania konta lub zmiany hasła, należy pobrać z serwera token. 9 | Przy asynchronicznej operacji, po wywołaniu funkcji \c gg_token() wynikową 10 | strukturę \c gg_http należy traktować tak jak każde połączenie HTTP. Po 11 | zakończeniu operacji asynchronicznej (\c state równe \c GG_STATE_DONE) lub 12 | wyjściu z funkcji \c gg_token() w operacji synchronicznej, w polu \c data 13 | struktury będzie znajdował się wskaźnik na strukturą \c gg_token zawierającą 14 | informacje o tokenie. W polu \c body struktury \c gg_http znajdzie się obrazek 15 | tokenu o rozmiarze \c body_size. Aplikacja powinna wyświetlić token 16 | użytkownikowi w celu odczytania i przekazania treści, która następnie zostana 17 | przekazana do odpowiedniej funkcji wywołania usługi dodatkowej. 18 | 19 | \section example Przykład pobierania tokenu 20 | 21 | \code 22 | struct gg_http *token; 23 | FILE *f; 24 | 25 | token = gg_token(0); 26 | 27 | if (!token) { 28 | błąd("Błąd pobierania tokenu"); 29 | exit(1); 30 | } 31 | 32 | plik = fopen(((struct gg_token *) token->data)->tokenid, "w"); 33 | 34 | if (!plik) { 35 | błąd("Błąd otwarcia pliku"); 36 | gg_token_free(token); 37 | exit(1); 38 | } 39 | 40 | fwrite(token->body, token->body_size, 1, plik); 41 | fclose(plik); 42 | 43 | gg_token_free(token); 44 | \endcode 45 | 46 | */ 47 | 48 | -------------------------------------------------------------------------------- /test/manual/Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = lib 2 | 3 | check_PROGRAMS = client userlist 4 | 5 | if HAVE_GLIBC 6 | check_PROGRAMS += dcc7 7 | else 8 | if HAVE_MINGW 9 | check_PROGRAMS += dcc7 10 | endif 11 | endif 12 | 13 | if HAVE_CURL_AND_EXPAT 14 | check_PROGRAMS += search 15 | endif 16 | # Wyłączone. 17 | # if HAVE_SPEEX_AND_GSM 18 | # check_PROGRAMS += voice7 19 | # endif 20 | 21 | EXTRA_PROGRAMS = client userlist dcc7 search voice7 22 | CLEANFILES = client userlist dcc7 search voice7 23 | 24 | AM_CPPFLAGS = -DGG_IGNORE_DEPRECATED -I$(top_srcdir)/include 25 | AM_LDFLAGS = @LDFLAGS_NO_INSTALL@ 26 | 27 | dcc7_LDADD = $(top_builddir)/src/libgadu.la 28 | dcc7_SOURCES = dcc7.c userconfig.c userconfig.h 29 | nodist_dcc7_SOURCES = libgadu-network.c 30 | 31 | client_LDADD = $(top_builddir)/src/libgadu.la 32 | client_SOURCES = client.c userconfig.c userconfig.h 33 | 34 | userlist_LDADD = $(top_builddir)/src/libgadu.la 35 | userlist_SOURCES = userlist.c userconfig.c userconfig.h 36 | 37 | search_SOURCES = search.c 38 | search_LDADD = lib/libsearch.a -lcurl -lexpat @MINGW_LDFLAGS@ 39 | 40 | voice7_CFLAGS = -DHAVE_SPEEX -DHAVE_GSM 41 | voice7_LDADD = $(top_builddir)/src/libgadu.la -lgsm -lspeex 42 | 43 | clean-local: 44 | rm -f *.log *-valgrind libgadu-*.c 45 | 46 | check-local: $(check_PROGRAMS) 47 | for i in $(check_PROGRAMS); do ln -sf ../valgrind $${i}-valgrind; done 48 | 49 | libgadu-%.c: ../../src/%.c 50 | $(AM_V_GEN)cat "$<" > "$@" 51 | -------------------------------------------------------------------------------- /include/strman.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 strman.h 21 | * 22 | * \brief Makra zapewniające kompatybilność API do obsługi operacji na stringach na różnych systemach 23 | */ 24 | 25 | #ifndef LIBGADU_STRMAN_H 26 | #define LIBGADU_STRMAN_H 27 | 28 | #include 29 | #include 30 | #include 31 | #ifndef _MSC_VER 32 | # include 33 | #else 34 | # define snprintf(str, size, format, ...) _snprintf_s(str, size, _TRUNCATE, format, __VA_ARGS__) 35 | # define vsnprintf(str, size, format, ap) vsnprintf_s(str, size, _TRUNCATE, format, ap) 36 | # define strdup _strdup 37 | # define strcasecmp _stricmp 38 | # define strncasecmp _strnicmp 39 | #endif 40 | 41 | #endif /* LIBGADU_STRMAN_H */ 42 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | lib_LTLIBRARIES = libgadu.la 2 | libgadu_la_SOURCES = common.c dcc.c dcc7.c debug.c deflate.c encoding.c endian.c events.c handlers.c http.c libgadu.c message.c network.c obsolete.c packets.pb-c.c protobuf.c pubdir.c pubdir50.c resolver.c sha1.c tvbuff.c tvbuilder.c 3 | libgadu_la_CFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include -DGG_IGNORE_DEPRECATED 4 | libgadu_la_LDFLAGS = -version-number 3:13 -export-symbols $(top_builddir)/src/libgadu.sym @MINGW_LDFLAGS@ @MINGW_LIBGEN@ 5 | EXTRA_libgadu_la_DEPENDENCIES = libgadu.sym 6 | libgadu_libextradir = $(libdir) 7 | libgadu_libextra_DATA = @MINGW_LIBDATA@ 8 | BUILT_SOURCES = libgadu.sym 9 | CLEANFILES = libgadu.sym libgadu.def libgadu.def.in 10 | EXTRA_DIST = libgadu.sym.in protobuf-c.c.patch 11 | 12 | if !HAVE_PROTOBUF_C 13 | libgadu_la_SOURCES += protobuf-c.c 14 | else 15 | EXTRA_DIST += protobuf-c.c 16 | endif 17 | 18 | packets.pb-c.c: ../packets.proto 19 | $(AM_V_GEN)cd $(top_builddir) ; sh protobufgen.sh 20 | 21 | if HAVE_MINGW 22 | # Win32 only - needed for MSVC libgadu.lib file generation. 23 | # To generate libgadu.lib file, do one of the following: 24 | # mingw: $ dlltool --def libgadu.def --output-lib libgadu.lib 25 | # msvc: > lib /machine:i386 /def:libgadu.def 26 | # you might also need to convert libgadu.h file with declspec.sh 27 | libgadu.def: libgadu.def.in 28 | $(AM_V_GEN)echo "LIBRARY libgadu-3.dll" > $@ 29 | $(AM_V_at)cat $< >> $@ 30 | 31 | libgadu.def.in: libgadu.la 32 | endif 33 | 34 | libgadu.sym: libgadu.sym.in ../config.h 35 | $(AM_V_GEN)cat "$<" > "$@" 36 | if IS_GPL_COMPLIANT 37 | $(AM_V_at)echo "gg_is_gpl_compliant" >> "$@" 38 | endif 39 | -------------------------------------------------------------------------------- /docs/status.dox: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | \defgroup status Zmiana statusu użytkownika 4 | \ingroup session 5 | 6 | \details 7 | 8 | Domyślnym statusem użytkownika po połączeniu z serwerem jest 9 | \c GG_STATUS_AVAIL. Domyślny status połączenia można zmienić za pomocą pól 10 | \ref gg_login_params::status "\c status" 11 | i \ref gg_login_params::status_descr "\c status_descr" 12 | struktury \c gg_login_params. Już po połączeniu z serwerem, status można 13 | zmieniać za pomocą poniższych funkcji. 14 | 15 | Przykład zmiany stanu na zajęty z opisem, widoczny tylko dla znajomych: 16 | 17 | \code 18 | gg_change_status_descr(sesja, GG_STATUS_INVISIBLE_DESCR | GG_STATUS_FRIENDS_MASK, "Nie przeszkadzać!"); 19 | \endcode 20 | 21 | Aby obserwować zmiany statusu kontaktów, należy najpierw 22 | \ref contacts "dodać do listy konktaktów" ich identyfikatory, a następnie 23 | obsługiwać \ref events-list "zdarzenia" związane ze zmianami statusu. 24 | 25 | Jeśli pole \ref gg_login_params::protocol_features "\c protocol_features" 26 | struktury \c gg_login_params zawiera \c GG_FEATURE_IMAGE_DESCR, informacja 27 | o tym, że status zawiera opis, jest dodatkowo przekazywana za pomocą flagi 28 | \c GG_STATUS_DESCR_MASK. To samo dotyczy zmiany statusów osób z listy 29 | kontaktów. 30 | 31 | Część opcji jest dostępna w postaci flag statusu, np. otrzymywanie linków 32 | od nieznajomych czy figurowanie jako klient mobilny. Można je ustawić za 33 | pomocą pola \ref gg_login_params::status_flags "\c status_flags" 34 | struktury \c gg_login_params lub funkcją \c gg_change_status_flags(). 35 | 36 | \bug Nie ma możliwości poprawnego odbierania statusów zawierających czas 37 | powrotu. 38 | 39 | */ 40 | -------------------------------------------------------------------------------- /test/automatic/connect.txt: -------------------------------------------------------------------------------- 1 | Jak to działa 2 | ------------- 3 | 4 | Program testuje mechanizm łączenia się z serwerem podczas występowania 5 | różnego rodzaju błędów -- od awarii serwera DNS, przez awarię łącza, po 6 | awarię serwerów Gadu-Gadu. 7 | 8 | Zasada działania programu polega na przejęciu funkcji systemowych i 9 | symulacji serwera Gadu-Gadu na komputerze lokalnym -- zarówno huba, jak 10 | i serwera właściwego. Serwery zwracają jedynie uproszczone odpowiedzi i 11 | nie analizują otrzymanych danych. Alokowane są 4 porty począwszy od 17219, 12 | dla symulacji huba, dla symulacji portu 8074, dla symulacji portu 443 i 13 | jedno zamknięte gniazdo do symulacji awarii serwera. To ostatnie jest 14 | przywiązane do portu, ale bez wywołania listen(). 15 | 16 | Podstawiona funkcja gethostbyname() dla appmsg.gadu-gadu.pl zwraca adres 17 | lokalny (127.0.67.67) lub błąd, jeśli symulujemy awarię DNS. Przejęcie 18 | funkcji connect() pozwala skierować ruch z portów 80, 8074 i 443 na jedno 19 | z lokalnie otwartych gniazd. Do symulacji awarii łącza lub całkowitej 20 | niedostępności serwera, połączenie jest przekierowywane na adres 192.0.2.1, 21 | który zgodnie z RFC 3330 jest zarezerwowany dla dokumentacji i przykładów, 22 | przez co mamy pewność, że jest niedostępny i że nie będziemy się łączyć 23 | z żadnym istniejącym hostem. 24 | 25 | Kolejne testy są uruchamiane dla różnych parametrów symulacji: 26 | - rozwiązywanie nazw działa lub nie, 27 | - port 80 działa lub nie, 28 | - port 8074 działa lub nie, 29 | - port 443 działa lub nie, 30 | - podano ręcznie adres serwera lub nie. 31 | 32 | Dla przyspieszenia testów, limit czasu połączenia przy operacjach 33 | asynchronicznych jest zmniejszany do 1 sekundy. Dla synchronicznych, 34 | funkcje systemowe od razu zwracają błąd typu ETIMEDOUT. 35 | -------------------------------------------------------------------------------- /protobufgen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | PROTOC_LEGACY=no 4 | 5 | if ! protoc-c --version | grep "protobuf-c 1." > /dev/null; then 6 | PROTOC_VER=`protoc-c --version | grep protobuf-c | cut -d' ' -f 2` 7 | if [ "$PROTOC_VER" = "" ]; then 8 | echo 9 | echo "########################################" 10 | echo "# WARNING" 11 | echo "########################################" 12 | echo 13 | echo "protoc-c < 1.0.0 found" 14 | echo "The output will be fixed to match the new API, but it's better to update." 15 | echo 16 | PROTOC_LEGACY=yes 17 | else 18 | echo "Invalid protoc-c version. Required 1.x.y, but $PROTOC_VER found." 19 | exit -2 20 | fi 21 | fi 22 | 23 | protoc-c --c_out=. packets.proto 24 | 25 | if [ $? != 0 ] ; then 26 | exit -1 27 | fi 28 | 29 | if [ "x$PROTOC_LEGACY" = "xyes" ]; then 30 | sed -i 's//"protobuf.h"/g' packets.pb-c.h 31 | 32 | # fix protoc-c < 0.14 output 33 | if ! cat packets.pb-c.c | grep "PROTOBUF_C_NO_DEPRECATED" > /dev/null; then 34 | sed -i 's| NULL,NULL \+/\* reserved1, reserved2 \*/| 0, 0, NULL, NULL|g' packets.pb-c.c 35 | fi 36 | 37 | # translate 0.15 output to 1.0.2 38 | sed -i 's/PROTOBUF_C_BEGIN_DECLS/PROTOBUF_C__BEGIN_DECLS/g' packets.pb-c.h 39 | sed -i 's/PROTOBUF_C_END_DECLS/PROTOBUF_C__END_DECLS/g' packets.pb-c.h 40 | sed -i 's/PROTOBUF_C_ASSERT/assert /g' packets.pb-c.c 41 | sed -i 's/PROTOBUF_C_OFFSETOF/offsetof/g' packets.pb-c.c 42 | sed -i 's/PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC/PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC/g' packets.pb-c.c 43 | sed -i 's/PROTOBUF_C_ENUM_DESCRIPTOR_MAGIC/PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC/g' packets.pb-c.c 44 | else 45 | sed -i 's//"protobuf.h"/g' packets.pb-c.h 46 | fi 47 | 48 | mv packets.pb-c.h include 49 | mv packets.pb-c.c src 50 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Wymienione osoby miały mniejszy lub większy wpływ na rozwój biblioteki 2 | i klienta. Niektórzy pisali kod, pomagali analizować protokół, testowali 3 | na różnych systemach, inni podsyłali patche i bugreporty. Jeśli ktoś 4 | został pominięty, niech da znać. W każdym razie za to, jak wygląda ekg i 5 | libgadu, odpowiedzialni są (w porządku alfabetycznym): 6 | 7 | Tomasz Chiliński 8 | Piotr Domagalski 9 | Rafał Florek 10 | Dawid Jarosz 11 | Tomasz Jarzynka 12 | Robert J. Woźny 13 | Wojtek Kaniewski 14 | Marek Kozina 15 | Marcin Krzyżanowski 16 | Piotr Kupisiewicz 17 | Adam Ludwikowski 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 | --------------------------------------------------------------------------------