Merged pidgin/main into default
--- a/Makefile.am Wed Oct 26 10:17:10 2016 +0000
+++ b/Makefile.am Sun Oct 30 12:03:44 2016 +0300
@@ -14,6 +14,8 @@
m4macros/introspection.m4 \
noinst_HEADERS = config.h package_revision.h
@@ -27,6 +29,9 @@
$(AM_V_at)if [ ! -f "$(top_builddir)libpurple/libpurple.la" ]; then \
$(MAKE) -C libpurple libpurple.la; \
+ $(AM_V_at)if [ ! -f "$(top_builddir)libpurple/protocols/facebook/libfacebook.la" ]; then \ + $(MAKE) -C libpurple/protocols/facebook libfacebook.la; \ $(AM_V_at)if [ ! -f "$(top_builddir)finch/libgnt/libgnt.la" ]; then \
$(MAKE) -C finch/libgnt libgnt.la; \
@@ -46,9 +51,6 @@
-distcheck-hook: libpurple/plugins/perl/common/Purple.pm pidgin/plugins/perl/common/Pidgin.pm
-# cp libpurple/plugins/perl/common/Gaim.pm $(distdir)/libpurple/plugins/perl/common
(cd po ; intltool-update -m 2>&1 | grep -v '^mismatched quotes.*\.py$$' | sed "s|current directory|po directory|" | grep . ; if [ $$? = 0 ] ; then exit 1 ; else exit 0 ; fi)
--- a/bitbucket-pipelines.yml Wed Oct 26 10:17:10 2016 +0000
+++ b/bitbucket-pipelines.yml Sun Oct 30 12:03:44 2016 +0300
@@ -5,7 +5,17 @@
- - ./autogen.sh --disable-kwallet --enable-debug --enable-gtk-doc
+ - ./autogen.sh --enable-debug --enable-gtk-doc - - make -s -j$(nproc) check
+ - make -s -j$(nproc) distcheck + image: pidgin/release-builder:release-2.x.y + - ./autogen.sh --enable-debug + - make -s -j$(nproc) check --- a/configure.ac Wed Oct 26 10:17:10 2016 +0000
+++ b/configure.ac Sun Oct 30 12:03:44 2016 +0300
@@ -155,9 +155,9 @@
AC_SUBST([PLUGIN_LDFLAGS])
-PURPLE_LIBS="\$(top_builddir)/libpurple/libpurple.la \$(GLIB_LIBS)"
-PIDGIN_LIBS="\$(top_builddir)/pidgin/libpidgin.la \$(GTK_LIBS)"
-FINCH_LIBS="\$(top_builddir)/finch/libfinch.la \$(top_builddir)/finch/libgnt/libgnt.la \$(GLIB_LIBS)"
+PURPLE_LIBS="\$(top_builddir)/libpurple/libpurple.la \$(GLIB_LIBS) \$(GPLUGIN_LIBS)" +PIDGIN_LIBS="\$(top_builddir)/pidgin/libpidgin.la \$(GTK_LIBS) \$(PURPLE_LIBS) \$(WEBKIT_LIBS)" +FINCH_LIBS="\$(top_builddir)/finch/libfinch.la \$(top_builddir)/finch/libgnt/libgnt.la \$(PURPLE_LIBS)" @@ -1181,58 +1181,38 @@
dnl #######################################################################
dnl # Check for Gadu-Gadu protocol library (libgadu)
dnl #######################################################################
-PKG_CHECK_MODULES(LIBGADU, [libgadu >= 1.12.0], [have_libgadu=yes], [have_libgadu=no])
+ [AS_HELP_STRING([--disable-libgadu], + [compile without libgadu (required for GaduGadu support)])], + enable_libgadu="$enableval", enable_libgadu="yes") -if test "x$have_libgadu" = "xyes"; then
- AC_CHECK_LIB(gadu, gg_is_gpl_compliant, , [
+if test "x$enable_libgadu" = "xyes"; then + PKG_CHECK_MODULES(LIBGADU, [libgadu >= 1.12.0], [ + AC_CHECK_LIB(gadu, gg_is_gpl_compliant, , [ + if test "x$force_deps" = "xyes" ; then libgadu is not compatible with the GPL when compiled with OpenSSL support.
-To compile against system libgadu, please recompile libgadu using:
+To link against libgadu, please recompile it using: ./configure --with-openssl=no
Then rerun this ./configure
-Falling back to using our own copy of libgadu.
-AM_CONDITIONAL(HAVE_LIBGADU, test "x$have_libgadu" = "xyes")
-if test "x$have_libgadu" = "xyes"; then
- AC_DEFINE(HAVE_LIBGADU, 1, [Linked with external libgadu])
- AC_CHECK_LIB(gnutls, gnutls_certificate_set_x509_system_trust, [gg_have_gnutls_csxst=yes], [gg_have_gnutls_csxst=no])
- if test "x$gg_have_gnutls_csxst" = "xno"; then
- for i in /etc/ssl/ca-bundle.pem \
- /etc/ssl/certs/ca-certificates.crt \
- /etc/pki/tls/cert.pem \
- /usr/local/share/certs/ca-root-nss.crt \
+ if test "x$have_libgadu" != "xyes" -a "x$force_deps" = "xyes" ; then +Libgadu development headers not found. +Use --disable-libgadu if you do not need GG (GaduGadu) support.
- if test "x$gg_have_gnutls_csxst" = "xyes"; then
- AC_DEFINE(HAVE_GNUTLS_CERTIFICATE_SET_X509_SYSTEM_TRUST, 1, [gnutls contains the gnutls_certificate_set_x509_system_trust function])
- if test "x$gg_gnutls_sts" != "x"; then
- AC_DEFINE_UNQUOTED(GG_CONFIG_GNUTLS_SYSTEM_TRUST_STORE, ["$gg_gnutls_sts"], [use the given file as GnuTLS default trust store])
- dnl # redundant - only here to stay compatible with libgadu upstream
- PKG_CHECK_MODULES([GNUTLS_2_10], [gnutls >= 2.10.0], [
- AC_DEFINE([HAVE_GNUTLS_2_10], [], [Defined if GnuTLS >= 2.10.0 is available.])
@@ -1259,6 +1239,9 @@
if test "x$silcincludes" != "xyes" -o "x$silcclient" != "xyes"; then
STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/silc//'`
+if test "x$have_libgadu" != "xyes" ; then + STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/gg//'` if test "x$is_win32" = "xyes" ; then
STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/zephyr//'`
@@ -1333,6 +1316,9 @@
if test "x$silcincludes" != "xyes" -o "x$silcclient" != "xyes"; then
DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/silc//'`
+if test "x$have_libgadu" != "xyes"; then + DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/gg//'` if test "x$is_win32" = "xyes" ; then
DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/zephyr//'`
@@ -1536,19 +1522,29 @@
dnl # Check for Secret Service headers
dnl #######################################################################
-# disabled - see secretservice.c
-#AC_ARG_ENABLE(libsecret, [AC_HELP_STRING([--disable-libsecret], [enable Secret Service support])], enable_secret_service=no, enable_secret_service=yes)
+AC_ARG_ENABLE(libsecret, + [AC_HELP_STRING([--disable-libsecret], [enable Secret Service support])], + enable_secret_service="$enableval", enable_secret_service="$is_not_win32") -#if test "x$enable_secret_service" = "xyes" ; then
-# PKG_CHECK_MODULES(SECRETSERVICE, [libsecret-1], [
-# AC_SUBST(SECRETSERVICE_CFLAGS)
-# AC_SUBST(SECRETSERVICE_LIBS)
-# AC_DEFINE(HAVE_SECRETSERVICE, 1, [Define if we have Secret Service.])
+if test "x$enable_secret_service" = "xyes" ; then + PKG_CHECK_MODULES(SECRETSERVICE, [libsecret-1], [ + AC_SUBST(SECRETSERVICE_CFLAGS) + AC_SUBST(SECRETSERVICE_LIBS) + AC_DEFINE(HAVE_SECRETSERVICE, 1, [Define if we have Secret Service.]) + enable_secret_service="no" + if test "x$force_deps" = "xyes" ; then +Libsecret development headers not found +Use --disable-libsecret if you do not need it. -#AM_CONDITIONAL(ENABLE_SECRETSERVICE, test "x$enable_secret_service" = "xyes")
-AM_CONDITIONAL(ENABLE_SECRETSERVICE, test "x1" = "x2")
+AM_CONDITIONAL(ENABLE_SECRETSERVICE, test "x$enable_secret_service" = "xyes") dnl #######################################################################
dnl # Check for GNOME Keyring headers
@@ -2254,7 +2250,6 @@
echo Build with Cyrus SASL support. : $enable_cyrus_sasl
echo Use kerberos 4 with zephyr.... : $kerberos
echo Use external libzephyr........ : $zephyr
-echo Use external libgadu.......... : $have_libgadu
echo Install pixmaps............... : $enable_pixmaps
echo Old tray icon compatibility... : $enable_traycompat
echo Install translations.......... : $enable_i18n
@@ -2269,7 +2264,7 @@
echo Build with GNOME Keyring...... : $enable_gnome_keyring
echo Build with KWallet............ : $enable_kwallet
-#echo Build with Secret Service..... : $enable_secret_service
+echo Build with Secret Service..... : $enable_secret_service echo Build with plugin support..... : $enable_plugins
echo Enable Introspection...........: $enable_introspection
--- a/doc/reference/libpurple/libpurple-docs.xml Wed Oct 26 10:17:10 2016 +0000
+++ b/doc/reference/libpurple/libpurple-docs.xml Sun Oct 30 12:03:44 2016 +0300
@@ -51,7 +51,6 @@
<xi:include href="xml/eventloop.xml" />
<xi:include href="xml/group.xml" />
<xi:include href="xml/xfer.xml" />
- <xi:include href="xml/purple-socket.xml" />
<xi:include href="xml/http.xml" />
<xi:include href="xml/idle.xml" />
<xi:include href="xml/keyring.xml" />
--- a/doc/reference/protocols/facebook/Makefile.am Wed Oct 26 10:17:10 2016 +0000
+++ b/doc/reference/protocols/facebook/Makefile.am Sun Oct 30 12:03:44 2016 +0300
@@ -106,7 +106,6 @@
# Other files to distribute
# e.g. EXTRA_DIST += version.xml.in
-EXTRA_DIST += version.xml.in
# Files not to distribute
# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types
--- a/libpurple/Makefile.am Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/Makefile.am Sun Oct 30 12:03:44 2016 +0300
@@ -94,7 +94,6 @@
@@ -179,7 +178,6 @@
@@ -284,11 +282,16 @@
$(AM_V_GEN)echo "#include \"marshallers.h\"" > marshallers.c
$(AM_V_at)$(GLIB_GENMARSHAL) --prefix=purple_smarshal $(srcdir)/marshallers.list --body >> marshallers.c
+# glib-mkenums doesn't handle VPATHs well, sed is used here to fix the +# include paths and documentation. +# Escaping possible . in $(srcdir) to \. for sed pattern. enums.h: $(srcdir)/enums.h.in $(purple_enumheaders)
$(AM_V_GEN)$(GLIB_MKENUMS) --template $(srcdir)/enums.h.in $(purple_enumheaders) > $@
+ sed -i 's,$(subst .,\.,$(srcdir))/,,g' $@ enums.c: $(srcdir)/enums.c.in $(purple_enumheaders)
$(AM_V_GEN)$(GLIB_MKENUMS) --template $(srcdir)/enums.c.in $(purple_enumheaders) > $@
+ sed -i 's,$(subst .,\.,$(srcdir))/,,g' $@ @@ -296,6 +299,9 @@
+ data/purple-url-handler.desktop @@ -320,10 +326,14 @@
prefs.h presence.h roomlist.h savedstatuses.h smiley.h smiley-list.h \
status.h server.h util.h xmlnode.h protocol.h protocols.h
+# Filter out enums.h and marshallers.h as they don't actually generate +# anything. This way making from a VPATH and distcheck doesn't fail due +# to not being able to find the enums.h or marshallers.h files if +# they've already been generated in the $(srcdir). purple_build_coreheaders = $(addprefix $(srcdir)/, $(purple_coreheaders)) \
$(addprefix $(srcdir)/ciphers/, $(purple_cipherheaders)) \
$(addprefix $(srcdir)/media/, $(purple_mediaheaders)) \
+ $(filter-out: enums.h marshallers.h, $(purple_builtheaders)) dbus_build_exported = $(addprefix $(srcdir)/, $(dbus_exported))
# We should probably make this better
dbus_signals = $(addprefix $(srcdir)/, $(purple_coresources)) \
@@ -344,7 +354,10 @@
dbus-server.$(OBJEXT): dbus-bindings.c dbus-signals.c dbus-types.c dbus-types.h
dbus-server.lo: dbus-bindings.c dbus-signals.c dbus-types.c dbus-types.h
-$(libpurple_la_OBJECTS): dbus-types.h
+# Declare these as dependencies so they're built even if `make distcheck` +# is run immediately after configuring. +$(libpurple_la_OBJECTS): dbus-types.h enums.h marshallers.h @@ -395,6 +408,10 @@
BUILT_SOURCES = $(purple_builtheaders) $(purple_builtsources)
+# Declare these as dependencies so they're built even if `make distcheck` +# is run immediately after configuring. +$(libpurple_la_OBJECTS): enums.h marshallers.h lib_LTLIBRARIES = libpurple.la $(libpurple_client_lib)
--- a/libpurple/Makefile.mingw Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/Makefile.mingw Sun Oct 30 12:03:44 2016 +0300
@@ -115,7 +115,6 @@
--- a/libpurple/connection.c Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/connection.c Sun Oct 30 12:03:44 2016 +0300
@@ -845,7 +845,6 @@
purple_http_conn_cancel_all(gc);
- _purple_socket_cancel_with_connection(gc);
purple_proxy_connect_cancel_with_handle(gc);
connections = g_list_remove(connections, gc);
--- a/libpurple/core.c Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/core.c Sun Oct 30 12:03:44 2016 +0300
@@ -190,7 +190,6 @@
@@ -254,7 +253,6 @@
purple_theme_manager_uninit();
- _purple_socket_uninit();
_purple_image_store_uninit();
--- a/libpurple/dbus-define-api.h Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/dbus-define-api.h Sun Oct 30 12:03:44 2016 +0300
@@ -1,3 +1,25 @@
+ * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA #ifndef __GI_SCANNER__ /* hide this file from g-ir-scanner */
#error "This file is not a valid C code and is not intended to be compiled."
--- a/libpurple/dbus-maybe.h Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/dbus-maybe.h Sun Oct 30 12:03:44 2016 +0300
@@ -1,3 +1,25 @@
+ * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA #ifndef _PURPLE_DBUS_MAYBE_H_
#define _PURPLE_DBUS_MAYBE_H_
--- a/libpurple/dbus-useful.c Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/dbus-useful.c Sun Oct 30 12:03:44 2016 +0300
@@ -1,3 +1,25 @@
+ * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA --- a/libpurple/dbus-useful.h Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/dbus-useful.h Sun Oct 30 12:03:44 2016 +0300
@@ -1,3 +1,25 @@
+ * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA #ifndef _PURPLE_DBUS_USEFUL_H_
#define _PURPLE_DBUS_USEFUL_H_
--- a/libpurple/http.c Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/http.c Sun Oct 30 12:03:44 2016 +0300
@@ -28,7 +28,7 @@
-#include "purple-socket.h"
@@ -57,9 +57,15 @@
typedef struct _PurpleHttpGzStream PurpleHttpGzStream;
+typedef void (*PurpleHttpSocketConnectCb)(PurpleHttpSocket *hs, + const gchar *error, gpointer _hc);
+ GSocketConnection *conn; + GCancellable *cancellable; @@ -175,7 +181,7 @@
struct _PurpleHttpKeepaliveRequest
- PurpleSocketConnectCb cb;
+ PurpleHttpSocketConnectCb cb; PurpleHttpKeepaliveHost *host;
@@ -247,7 +253,7 @@
static PurpleHttpKeepaliveRequest *
purple_http_keepalive_pool_request(PurpleHttpKeepalivePool *pool,
PurpleConnection *gc, const gchar *host, int port, gboolean is_ssl,
- PurpleSocketConnectCb cb, gpointer user_data);
+ PurpleHttpSocketConnectCb cb, gpointer user_data); purple_http_keepalive_pool_request_cancel(PurpleHttpKeepaliveRequest *req);
@@ -463,23 +469,69 @@
return g_strdup_printf("%c:%s:%d", (is_ssl ? 'S' : 'R'), host, port);
+purple_http_socket_connect_new_cb(GObject *source, GAsyncResult *res, + PurpleHttpSocket *hs = user_data; + GSocketConnection *conn; + PurpleHttpSocketConnectCb cb; + conn = g_socket_client_connect_to_host_finish(G_SOCKET_CLIENT(source), + cb = g_object_steal_data(source, "cb"); + cb_data = g_object_steal_data(source, "cb_data"); + if (!g_error_matches(error, + G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + cb(hs, error->message, cb_data); static PurpleHttpSocket *
purple_http_socket_connect_new(PurpleConnection *gc, const gchar *host,
- int port, gboolean is_ssl, PurpleSocketConnectCb cb, gpointer user_data)
+ int port, gboolean is_ssl, + PurpleHttpSocketConnectCb cb, gpointer user_data) - PurpleHttpSocket *hs = g_new0(PurpleHttpSocket, 1);
- hs->ps = purple_socket_new(gc);
- purple_socket_set_data(hs->ps, "hs", hs);
- purple_socket_set_tls(hs->ps, is_ssl);
- purple_socket_set_host(hs->ps, host);
- purple_socket_set_port(hs->ps, port);
- if (!purple_socket_connect(hs->ps, cb, user_data)) {
- purple_socket_destroy(hs->ps);
+ client = purple_gio_socket_client_new( + purple_connection_get_account(gc), &error); + purple_debug_error("http", "Error connecting to '%s:%d': %s", + host, port, error->message); + hs = g_new0(PurpleHttpSocket, 1); + hs->cancellable = g_cancellable_new(); + g_socket_client_set_tls(client, is_ssl); + g_object_set_data(G_OBJECT(client), "cb", cb); + g_object_set_data(G_OBJECT(client), "cb_data", user_data); + g_socket_client_connect_to_host_async(client, + host, port, hs->cancellable, + purple_http_socket_connect_new_cb, hs); + g_object_unref(client); if (purple_debug_is_verbose())
purple_debug_misc("http", "new socket created: %p\n", hs);
@@ -495,7 +547,26 @@
if (purple_debug_is_verbose())
purple_debug_misc("http", "destroying socket: %p\n", hs);
- purple_socket_destroy(hs->ps);
+ if (hs->input_source > 0) { + g_source_remove(hs->input_source); + if (hs->output_source > 0) { + g_source_remove(hs->output_source); + if (hs->cancellable != NULL) { + g_cancellable_cancel(hs->cancellable); + g_clear_object(&hs->cancellable); + if (hs->conn != NULL) { + purple_gio_graceful_close(G_IO_STREAM(hs->conn), NULL, NULL); + g_clear_object(&hs->conn); @@ -682,10 +753,9 @@
static void _purple_http_gen_headers(PurpleHttpConnection *hc);
-static gboolean _purple_http_recv_loopbody(PurpleHttpConnection *hc, gint fd);
-static void _purple_http_recv(gpointer _hc, gint fd,
- PurpleInputCondition cond);
-static void _purple_http_send(gpointer _hc, gint fd, PurpleInputCondition cond);
+static gboolean _purple_http_recv_loopbody(PurpleHttpConnection *hc); +static gboolean _purple_http_recv(GObject *source, gpointer _hc); +static gboolean _purple_http_send(GObject *source, gpointer _hc); /* closes current connection (if exists), estabilishes one and proceeds with
@@ -1077,21 +1147,33 @@
return _purple_http_recv_body_data(hc, buf, len);
-static gboolean _purple_http_recv_loopbody(PurpleHttpConnection *hc, gint fd)
+static gboolean _purple_http_recv_loopbody(PurpleHttpConnection *hc)
- len = purple_socket_read(hc->socket->ps, (guchar*)buf, sizeof(buf));
+ len = g_pollable_input_stream_read_nonblocking( + G_POLLABLE_INPUT_STREAM( + g_io_stream_get_input_stream( + G_IO_STREAM(hc->socket->conn))), + buf, sizeof(buf), hc->socket->cancellable, got_anything = (len > 0);
- if (len < 0 && errno == EAGAIN)
+ if (len < 0 && (g_error_matches(error, + G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK) || + G_IO_ERROR, G_IO_ERROR_CANCELLED))) { _purple_http_error(hc, _("Error reading from %s: %s"),
- hc->url->host, g_strerror(errno));
+ hc->url->host, error->message); @@ -1270,11 +1352,13 @@
-static void _purple_http_recv(gpointer _hc, gint fd, PurpleInputCondition cond)
+static gboolean _purple_http_recv(GObject *source, gpointer _hc) PurpleHttpConnection *hc = _hc;
- while (_purple_http_recv_loopbody(hc, fd));
+ while (_purple_http_recv_loopbody(hc)); + return G_SOURCE_CONTINUE; static void _purple_http_send_got_data(PurpleHttpConnection *hc,
@@ -1305,17 +1389,19 @@
hc->request->contents_length = estimated_length;
-static void _purple_http_send(gpointer _hc, gint fd, PurpleInputCondition cond)
+static gboolean _purple_http_send(GObject *source, gpointer _hc) PurpleHttpConnection *hc = _hc;
gboolean writing_headers;
/* Waiting for data. This could be written more efficiently, by removing
* (and later, adding) hs->inpa. */
if (hc->contents_reader_requested)
+ return G_SOURCE_CONTINUE; _purple_http_gen_headers(hc);
@@ -1328,7 +1414,7 @@
hc->request_header_written;
} else if (hc->request->contents_reader) {
if (hc->contents_reader_requested)
- return; /* waiting for data */
+ return G_SOURCE_CONTINUE; /* waiting for data */ if (!hc->contents_reader_buffer)
hc->contents_reader_buffer = g_string_new("");
if (hc->contents_reader_buffer->len == 0) {
@@ -1341,7 +1427,7 @@
PURPLE_HTTP_MAX_READ_BUFFER_LEN,
hc->request->contents_reader_data,
_purple_http_send_got_data);
+ return G_SOURCE_CONTINUE; write_from = hc->contents_reader_buffer->str;
write_len = hc->contents_reader_buffer->len;
@@ -1356,12 +1442,21 @@
purple_debug_warning("http", "Nothing to write\n");
- written = purple_socket_write(hc->socket->ps,
- (const guchar*)write_from, write_len);
+ written = g_pollable_output_stream_write_nonblocking( + G_POLLABLE_OUTPUT_STREAM( + g_io_stream_get_output_stream( + G_IO_STREAM(hc->socket->conn))), + write_from, write_len, hc->socket->cancellable, - if (written < 0 && errno == EAGAIN)
+ if (written < 0 && (g_error_matches(error, + G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK) || + G_IO_ERROR, G_IO_ERROR_CANCELLED))) { + return G_SOURCE_CONTINUE; if (hc->request_header_written == 0 &&
@@ -1370,21 +1465,22 @@
purple_debug_info("http", "Keep-alive connection "
"expired (when writing), retrying...\n");
purple_http_conn_retry(hc);
+ _purple_http_error(hc, _("Error writing to %s: %s"), + hc->url->host, error->message); - _purple_http_error(hc, _("Error writing to %s: %s"),
- hc->url->host, g_strerror(errno));
+ return G_SOURCE_CONTINUE; hc->request_header_written += written;
purple_http_conn_notify_progress_watcher(hc);
if (hc->request_header_written < hc->request_header->len)
+ return G_SOURCE_CONTINUE; if (hc->request->contents_length > 0)
+ return G_SOURCE_CONTINUE; hc->request_contents_written += written;
purple_http_conn_notify_progress_watcher(hc);
@@ -1394,14 +1490,24 @@
hc->request_contents_written <
(guint)hc->request->contents_length)
+ return G_SOURCE_CONTINUE; /* request is completely written, let's read the response */
- purple_socket_watch(hc->socket->ps, PURPLE_INPUT_READ,
- _purple_http_recv, hc);
+ gsource = g_pollable_input_stream_create_source( + G_POLLABLE_INPUT_STREAM( + g_io_stream_get_input_stream( + G_IO_STREAM(hc->socket->conn))), + g_source_set_callback(gsource, + (GSourceFunc)_purple_http_recv, hc, NULL); + hc->socket->input_source = g_source_attach(gsource, NULL); + g_source_unref(gsource); + hc->socket->output_source = 0; + return G_SOURCE_REMOVE; static void _purple_http_disconnect(PurpleHttpConnection *hc,
@@ -1426,13 +1532,10 @@
-_purple_http_connected(PurpleSocket *ps, const gchar *error, gpointer _hc)
+_purple_http_connected(PurpleHttpSocket *hs, const gchar *error, gpointer _hc) - PurpleHttpSocket *hs = NULL;
PurpleHttpConnection *hc = _hc;
- hs = purple_socket_get_data(ps, "hs");
hc->socket_request = NULL;
@@ -1443,7 +1546,14 @@
- purple_socket_watch(ps, PURPLE_INPUT_WRITE, _purple_http_send, hc);
+ source = g_pollable_output_stream_create_source( + G_POLLABLE_OUTPUT_STREAM( + g_io_stream_get_output_stream(G_IO_STREAM(hs->conn))), + g_source_set_callback(source, + (GSourceFunc)_purple_http_send, hc, NULL); + hc->socket->output_source = g_source_attach(source, NULL); + g_source_unref(source); static gboolean _purple_http_reconnect(PurpleHttpConnection *hc)
@@ -2155,7 +2265,7 @@
static PurpleHttpKeepaliveRequest *
purple_http_keepalive_pool_request(PurpleHttpKeepalivePool *pool,
PurpleConnection *gc, const gchar *host, int port, gboolean is_ssl,
- PurpleSocketConnectCb cb, gpointer user_data)
+ PurpleHttpSocketConnectCb cb, gpointer user_data) PurpleHttpKeepaliveRequest *req;
PurpleHttpKeepaliveHost *kahost;
@@ -2198,19 +2308,15 @@
-_purple_http_keepalive_socket_connected(PurpleSocket *ps,
+_purple_http_keepalive_socket_connected(PurpleHttpSocket *hs, const gchar *error, gpointer _req)
- PurpleHttpSocket *hs = NULL;
PurpleHttpKeepaliveRequest *req = _req;
- hs = purple_socket_get_data(ps, "hs");
- req->cb(ps, error, req->user_data);
+ req->cb(hs, error, req->user_data); @@ -2266,7 +2372,7 @@
purple_http_keepalive_host_process_queue(host);
- req->cb(hs->ps, NULL, req->user_data);
+ req->cb(hs, NULL, req->user_data); @@ -2337,7 +2443,16 @@
if (purple_debug_is_verbose())
purple_debug_misc("http", "releasing a socket: %p\n", hs);
- purple_socket_watch(hs->ps, 0, NULL, NULL);
+ if (hs->input_source > 0) { + g_source_remove(hs->input_source); + if (hs->output_source > 0) { + g_source_remove(hs->output_source); --- a/libpurple/internal.h Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/internal.h Sun Oct 30 12:03:44 2016 +0300
@@ -360,31 +360,6 @@
_purple_fstat(int fd, GStatBuf *st);
- * _purple_socket_cancel_with_connection:
- * Cancels all #PurpleSocket instances bound with @gc.
-_purple_socket_cancel_with_connection(PurpleConnection *gc);
- * _purple_socket_init: (skip)
- * Initializes the #PurpleSocket subsystem.
-_purple_socket_init(void);
- * _purple_socket_uninit: (skip)
- * Uninitializes the #PurpleSocket subsystem.
-_purple_socket_uninit(void);
* _purple_message_init: (skip)
* Initializes the #PurpleMessage subsystem.
--- a/libpurple/plugins/keyrings/secretservice.c Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/plugins/keyrings/secretservice.c Sun Oct 30 12:03:44 2016 +0300
@@ -21,17 +21,15 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-#error "This keyring needs some more work (see TODO)"
- * This keyring needs some more work, so it will be disabled until its quality
- * was raised. Some of the pain points:
- * - throws a lot of g_warnings
- * - it doesn't notify about some backend faults (like access denied), some of
- * them are not handled at all
- * - it could use libsecret's Complete API
- * - code formatting could be better
+ * This keyring now works (at the time of this writing), but there are + * some inconvenient edge cases. When looking up passwords, libsecret + * doesn't error if the keyring is locked. Therefore, it appears to + * this plugin that there's no stored password. libpurple seems to + * handle this as gracefully as possible, but it's still inconvenient. + * This plugin could possibly be ported to use libsecret's "Complete API" + * to resolve this if desired. @@ -53,6 +51,7 @@
#define SECRETSERVICE_DOMAIN (g_quark_from_static_string(SECRETSERVICE_ID))
static PurpleKeyring *keyring_handler = NULL;
+static GCancellable *keyring_cancellable = NULL; static const SecretSchema purple_schema = {
"im.pidgin.Purple", SECRET_SCHEMA_NONE,
@@ -78,6 +77,62 @@
/***********************************************/
+ss_g_error_to_keyring_error(GError **error, PurpleAccount *account) + GError *new_error = NULL; + g_return_if_fail(error != NULL); + if (g_error_matches(old_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + new_error = g_error_new(PURPLE_KEYRING_ERROR, + PURPLE_KEYRING_ERROR_CANCELLED, + _("Operation cancelled.")); + } else if (g_error_matches(old_error, G_DBUS_ERROR, + G_DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND) || + g_error_matches(old_error, G_DBUS_ERROR, + G_DBUS_ERROR_IO_ERROR)) { + purple_debug_info("keyring-libsecret", + "Failed to communicate with Secret " + "Service (account: %s (%s)).\n", + purple_account_get_username(account), + purple_account_get_protocol_id(account)); + new_error = g_error_new(PURPLE_KEYRING_ERROR, + PURPLE_KEYRING_ERROR_BACKENDFAIL, + "Failed to communicate with Secret " + "Service (account: %s).", + purple_account_get_username(account)); + } else if (g_error_matches(old_error, SECRET_ERROR, + SECRET_ERROR_IS_LOCKED)) { + purple_debug_info("keyring-libsecret", + "Secret Service is locked (account: %s (%s)).\n", + purple_account_get_username(account), + purple_account_get_protocol_id(account)); + new_error = g_error_new(PURPLE_KEYRING_ERROR, + PURPLE_KEYRING_ERROR_ACCESSDENIED, + "Secret Service is locked (account: %s).", + purple_account_get_username(account)); + purple_debug_error("keyring-libsecret", + "Unknown error (account: %s (%s), " + "domain: %s, code: %d): %s.\n", + purple_account_get_username(account), + purple_account_get_protocol_id(account), + g_quark_to_string(old_error->domain), + old_error->code, old_error->message); + new_error = g_error_new(PURPLE_KEYRING_ERROR, + PURPLE_KEYRING_ERROR_BACKENDFAIL, + "Unknown error (account: %s).", + purple_account_get_username(account)); + g_propagate_error(error, new_error); ss_read_continue(GObject *object, GAsyncResult *result, gpointer data)
InfoStorage *storage = data;
@@ -89,53 +144,19 @@
password = secret_password_lookup_finish(result, &error);
- int code = error->code;
- case G_DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND:
- case G_DBUS_ERROR_IO_ERROR:
- error = g_error_new(PURPLE_KEYRING_ERROR,
- PURPLE_KEYRING_ERROR_BACKENDFAIL,
- "Failed to communicate with Secret "
- "Service (account : %s).",
- purple_account_get_username(account));
- cb(account, NULL, error, storage->user_data);
- purple_debug_error("keyring-libsecret",
- "Unknown error (account: %s (%s), "
- "domain: %s, code: %d): %s.\n",
- purple_account_get_username(account),
- purple_account_get_protocol_id(account),
- g_quark_to_string(error->domain), code,
- error = g_error_new(PURPLE_KEYRING_ERROR,
- PURPLE_KEYRING_ERROR_BACKENDFAIL,
- "Unknown error (account : %s).",
- purple_account_get_username(account));
- cb(account, NULL, error, storage->user_data);
+ ss_g_error_to_keyring_error(&error, account); } else if (password == NULL) {
error = g_error_new(PURPLE_KEYRING_ERROR,
PURPLE_KEYRING_ERROR_NOPASSWORD,
"No password found for account: %s",
purple_account_get_username(account));
- cb(account, NULL, error, storage->user_data);
- cb(account, password, NULL, storage->user_data);
+ cb(account, password, error, storage->user_data); @@ -148,74 +169,57 @@
storage->user_data = data;
- secret_password_lookup(&purple_schema, NULL, ss_read_continue, storage,
+ secret_password_lookup(&purple_schema, keyring_cancellable, + ss_read_continue, storage, "user", purple_account_get_username(account),
"protocol", purple_account_get_protocol_id(account), NULL);
-ss_save_continue(GObject *object, GAsyncResult *result, gpointer data)
+ss_save_continue(GError *error, gpointer data) InfoStorage *storage = data;
PurpleKeyringSaveCallback cb;
account = storage->account;
- secret_password_store_finish(result, &error);
- int code = error->code;
- case G_DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND:
- case G_DBUS_ERROR_IO_ERROR:
- purple_debug_info("keyring-libsecret",
- "Failed to communicate with Secret "
- "Service (account : %s (%s)).\n",
- purple_account_get_username(account),
- purple_account_get_protocol_id(account));
- error = g_error_new(PURPLE_KEYRING_ERROR,
- PURPLE_KEYRING_ERROR_BACKENDFAIL,
- "Failed to communicate with Secret Service (account : %s).",
- purple_account_get_username(account));
- cb(account, error, storage->user_data);
- purple_debug_error("keyring-libsecret",
- "Unknown error (account: %s (%s), "
- "domain: %s, code: %d): %s.\n",
- purple_account_get_username(account),
- purple_account_get_protocol_id(account),
- g_quark_to_string(error->domain), code,
- error = g_error_new(PURPLE_KEYRING_ERROR,
- PURPLE_KEYRING_ERROR_BACKENDFAIL,
- "Unknown error (account : %s).",
- purple_account_get_username(account));
- cb(account, error, storage->user_data);
+ ss_g_error_to_keyring_error(&error, account); purple_debug_info("keyring-libsecret", "Password for %s updated.\n",
purple_account_get_username(account));
- cb(account, NULL, storage->user_data);
+ cb(account, error, storage->user_data); +ss_store_continue(GObject *object, GAsyncResult *result, gpointer data) + secret_password_store_finish(result, &error); + ss_save_continue(error, data); +ss_clear_continue(GObject *object, GAsyncResult *result, gpointer data) + secret_password_clear_finish(result, &error); + ss_save_continue(error, data); ss_save(PurpleAccount *account,
PurpleKeyringSaveCallback cb,
@@ -237,7 +241,8 @@
label = g_strdup_printf(_("Pidgin IM password for account %s"), username);
secret_password_store(&purple_schema, SECRET_COLLECTION_DEFAULT,
- label, password, NULL, ss_save_continue, storage,
+ label, password, keyring_cancellable, + ss_store_continue, storage, "protocol", purple_account_get_protocol_id(account),
@@ -249,27 +254,42 @@
purple_account_get_username(account),
purple_account_get_protocol_id(account));
- secret_password_clear(&purple_schema, NULL, ss_save_continue,
- storage, "user", purple_account_get_username(account),
+ secret_password_clear(&purple_schema, keyring_cancellable, + ss_clear_continue, storage, + "user", purple_account_get_username(account), "protocol", purple_account_get_protocol_id(account),
+ g_cancellable_cancel(keyring_cancellable); + /* Swap out cancelled cancellable for new one for further operations */ + g_clear_object(&keyring_cancellable); + keyring_cancellable = g_cancellable_new(); + keyring_cancellable = g_cancellable_new(); keyring_handler = purple_keyring_new();
purple_keyring_set_name(keyring_handler, _(SECRETSERVICE_NAME));
purple_keyring_set_id(keyring_handler, SECRETSERVICE_ID);
purple_keyring_set_read_password(keyring_handler, ss_read);
purple_keyring_set_save_password(keyring_handler, ss_save);
+ purple_keyring_set_cancel_requests(keyring_handler, ss_cancel); purple_keyring_set_close_keyring(keyring_handler, ss_close);
purple_keyring_register(keyring_handler);
@@ -284,6 +304,8 @@
purple_keyring_unregister(keyring_handler);
purple_keyring_free(keyring_handler);
+ g_clear_object(&keyring_cancellable); /***********************************************/
--- a/libpurple/protocols/bonjour/Makefile.am Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/protocols/bonjour/Makefile.am Sun Oct 30 12:03:44 2016 +0300
@@ -1,5 +1,6 @@
@@ -23,7 +24,7 @@
-BONJOURSOURCES += dns_sd_proxy.c
+BONJOURSOURCES += dns_sd_proxy.c mdns_dns_sd.c BONJOURSOURCES += mdns_avahi.c
--- a/libpurple/protocols/facebook/Makefile.am Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/protocols/facebook/Makefile.am Sun Oct 30 12:03:44 2016 +0300
@@ -52,7 +52,7 @@
pkg_LTLIBRARIES = libfacebook.la
libfacebook_la_SOURCES = $(FACEBOOKSOURCES)
-libfacebook_la_LIBADD = @PURPLE_LIBS@
+libfacebook_la_LIBADD = @PURPLE_LIBS@ $(JSON_LIBS) --- a/libpurple/protocols/facebook/facebook.c Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/protocols/facebook/facebook.c Sun Oct 30 12:03:44 2016 +0300
@@ -332,8 +332,8 @@
gc = fb_data_get_connection(fata);
- if (error->domain == FB_MQTT_SSL_ERROR) {
- purple_connection_ssl_error(gc, error->code);
+ if (error->domain == G_IO_ERROR) { + purple_connection_g_error(gc, error); --- a/libpurple/protocols/facebook/mqtt.c Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/protocols/facebook/mqtt.c Sun Oct 30 12:03:44 2016 +0300
@@ -28,7 +28,8 @@
+#include "queuedoutputstream.h" @@ -37,17 +38,17 @@
- PurpleSslConnection *gsc;
+ GBufferedInputStream *input; + PurpleQueuedOutputStream *output; + GCancellable *cancellable;
struct _FbMqttMessagePrivate
@@ -65,6 +66,8 @@
G_DEFINE_TYPE(FbMqtt, fb_mqtt, G_TYPE_OBJECT);
G_DEFINE_TYPE(FbMqttMessage, fb_mqtt_message, G_TYPE_OBJECT);
+static void fb_mqtt_read_packet(FbMqtt *mqtt); fb_mqtt_dispose(GObject *obj)
@@ -73,7 +76,6 @@
g_byte_array_free(priv->rbuf, TRUE);
- g_byte_array_free(priv->wbuf, TRUE);
@@ -161,7 +163,6 @@
priv->rbuf = g_byte_array_new();
- priv->wbuf = g_byte_array_new();
@@ -205,18 +206,6 @@
-fb_mqtt_ssl_error_quark(void)
- if (G_UNLIKELY(q == 0)) {
- q = g_quark_from_static_string("fb-mqtt-ssl-error-quark");
fb_mqtt_new(PurpleConnection *gc)
@@ -240,33 +229,47 @@
g_return_if_fail(FB_IS_MQTT(mqtt));
- purple_input_remove(priv->wev);
- purple_input_remove(priv->rev);
purple_timeout_remove(priv->tev);
- if (priv->gsc != NULL) {
- purple_ssl_close(priv->gsc);
+ if (priv->cancellable != NULL) { + g_cancellable_cancel(priv->cancellable); + g_clear_object(&priv->cancellable); - if (priv->wbuf->len > 0) {
- fb_util_debug_warning("Closing with unwritten data");
+ if (priv->conn != NULL) { + purple_gio_graceful_close(priv->conn, + G_INPUT_STREAM(priv->input), + G_OUTPUT_STREAM(priv->output)); + g_clear_object(&priv->input); + g_clear_object(&priv->output); + g_clear_object(&priv->conn); g_byte_array_set_size(priv->rbuf, 0);
- g_byte_array_set_size(priv->wbuf, 0);
+fb_mqtt_take_error(FbMqtt *mqtt, GError *err, const gchar *prefix) + if (g_error_matches(err, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + /* Return as cancelled means the connection is closing */ + /* Now we can check for programming errors */ + g_return_if_fail(FB_IS_MQTT(mqtt)); + g_prefix_error(&err, "%s: ", prefix); + g_signal_emit_by_name(mqtt, "error", err); @@ -344,74 +347,130 @@
-fb_mqtt_cb_read(gpointer data, gint fd, PurpleInputCondition cond)
+fb_mqtt_cb_fill(GObject *source, GAsyncResult *res, gpointer data) + GBufferedInputStream *input = G_BUFFERED_INPUT_STREAM(source); + ret = g_buffered_input_stream_fill_finish(input, res, &err); + err = g_error_new_literal(G_IO_ERROR, + G_IO_ERROR_CONNECTION_CLOSED, + _("Connection closed")); + fb_mqtt_take_error(mqtt, err, _("Failed to read fixed header")); + fb_mqtt_read_packet(mqtt); +fb_mqtt_cb_read_packet(GObject *source, GAsyncResult *res, gpointer data) - FbMqttPrivate *priv = mqtt->priv;
- /* Reset the read buffer */
- g_byte_array_set_size(priv->rbuf, 0);
+ ret = g_input_stream_read_finish(G_INPUT_STREAM(source), res, &err); - res = purple_ssl_read(priv->gsc, &byte, sizeof byte);
- g_byte_array_append(priv->rbuf, &byte, sizeof byte);
- if (res != sizeof byte) {
- fb_mqtt_error(mqtt, FB_MQTT_ERROR_GENERAL,
- _("Failed to read fixed header"));
+ err = g_error_new_literal(G_IO_ERROR, + G_IO_ERROR_CONNECTION_CLOSED, + _("Connection closed"));
- res = purple_ssl_read(priv->gsc, &byte, sizeof byte);
- g_byte_array_append(priv->rbuf, &byte, sizeof byte);
+ fb_mqtt_take_error(mqtt, err, _("Failed to read packet data")); - if (res != sizeof byte) {
- fb_mqtt_error(mqtt, FB_MQTT_ERROR_GENERAL,
- _("Failed to read packet size"));
- priv->remz += (byte & 127) * mult;
- } while ((byte & 128) != 0);
- size = MIN(priv->remz, sizeof buf);
- rize = purple_ssl_read(priv->gsc, buf, size);
+ g_input_stream_read_async(G_INPUT_STREAM(source), + priv->rbuf->len - priv->remz, priv->remz, + G_PRIORITY_DEFAULT, priv->cancellable, + fb_mqtt_cb_read_packet, mqtt);
- fb_mqtt_error(mqtt, FB_MQTT_ERROR_GENERAL,
- _("Failed to read packet data"));
+ msg = fb_mqtt_message_new_bytes(priv->rbuf); - g_byte_array_append(priv->rbuf, buf, rize);
+ if (G_UNLIKELY(msg == NULL)) { + fb_mqtt_error(mqtt, FB_MQTT_ERROR_GENERAL, + _("Failed to parse message"));
- msg = fb_mqtt_message_new_bytes(priv->rbuf);
+ fb_mqtt_read(mqtt, msg); + /* Read another packet if connection wasn't reset in fb_mqtt_read() */ + if (fb_mqtt_connected(mqtt, FALSE)) { + fb_mqtt_read_packet(mqtt); - if (G_UNLIKELY(msg == NULL)) {
- fb_mqtt_error(mqtt, FB_MQTT_ERROR_GENERAL,
- _("Failed to parse message"));
+fb_mqtt_read_packet(FbMqtt *mqtt) + FbMqttPrivate *priv = mqtt->priv; + const guint8 const *buf; + buf = g_buffered_input_stream_peek_buffer(priv->input, &count); + /* Start at 1 to skip the first byte */ + /* Not enough data yet, try again later */ - fb_mqtt_read(mqtt, msg);
+ size += (byte & 127) * mult; + } while ((byte & 128) != 0); + /* Add header to size */ + g_byte_array_set_size(priv->rbuf, size); + /* TODO: Use g_input_stream_read_all_async() when available. */ + /* TODO: Alternately, it would be nice to let the + * FbMqttMessage directly use the GBufferedInputStream + * buffer instead of copying it, provided it's consumed + * before the next read. + g_input_stream_read_async(G_INPUT_STREAM(priv->input), + priv->rbuf->data, priv->rbuf->len, + G_PRIORITY_DEFAULT, priv->cancellable, + fb_mqtt_cb_read_packet, mqtt); + g_buffered_input_stream_fill_async(priv->input, -1, + G_PRIORITY_DEFAULT, priv->cancellable, + fb_mqtt_cb_fill, mqtt); @@ -519,27 +578,16 @@
-fb_mqtt_cb_write(gpointer data, gint fd, PurpleInputCondition cond)
+fb_mqtt_cb_flush(GObject *source, GAsyncResult *res, gpointer data) - FbMqttPrivate *priv = mqtt->priv;
- wize = purple_ssl_write(priv->gsc, priv->wbuf->data, priv->wbuf->len);
- fb_mqtt_error(mqtt, FB_MQTT_ERROR_GENERAL,
- _("Failed to write data"));
+ if (!g_output_stream_flush_finish(G_OUTPUT_STREAM(source), + fb_mqtt_take_error(mqtt, err, _("Failed to write data"));
- g_byte_array_remove_range(priv->wbuf, 0, wize);
- if (priv->wbuf->len < 1) {
@@ -548,6 +596,7 @@
FbMqttMessagePrivate *mriv;
g_return_if_fail(FB_IS_MQTT(mqtt));
g_return_if_fail(FB_IS_MQTT_MESSAGE(msg));
@@ -566,46 +615,46 @@
"Writing %d (flags: 0x%0X)",
mriv->type, mriv->flags);
- g_byte_array_append(priv->wbuf, bytes->data, bytes->len);
- fb_mqtt_cb_write(mqtt, priv->gsc->fd, PURPLE_INPUT_WRITE);
+ /* TODO: Would be nice to refactor this to not require copying bytes */ + gbytes = g_bytes_new(bytes->data, bytes->len); + purple_queued_output_stream_push_bytes(priv->output, gbytes);
- priv->wev = purple_input_add(priv->gsc->fd,
- fb_mqtt_cb_write, mqtt);
+ if (!g_output_stream_has_pending(G_OUTPUT_STREAM(priv->output))) { + g_output_stream_flush_async(G_OUTPUT_STREAM(priv->output), + G_PRIORITY_DEFAULT, priv->cancellable, + fb_mqtt_cb_flush, mqtt); -fb_mqtt_cb_open(gpointer data, PurpleSslConnection *ssl,
- PurpleInputCondition cond)
+fb_mqtt_cb_open(GObject *source, GAsyncResult *res, gpointer data) - FbMqttPrivate *priv = mqtt->priv;
+ GSocketConnection *conn; + conn = g_socket_client_connect_to_host_finish(G_SOCKET_CLIENT(source), + fb_mqtt_take_error(mqtt, err, NULL); fb_mqtt_timeout_clear(mqtt);
- priv->rev = purple_input_add(priv->gsc->fd, PURPLE_INPUT_READ,
- fb_mqtt_cb_read, mqtt);
- g_signal_emit_by_name(mqtt, "open");
-fb_mqtt_cb_open_error(PurpleSslConnection *ssl, PurpleSslErrorType error,
- FbMqttPrivate *priv = mqtt->priv;
+ priv->conn = G_IO_STREAM(conn); + priv->input = G_BUFFERED_INPUT_STREAM(g_buffered_input_stream_new( + g_io_stream_get_input_stream(priv->conn))); + priv->output = purple_queued_output_stream_new( + g_io_stream_get_output_stream(priv->conn)); - str = purple_ssl_strerror(error);
- err = g_error_new_literal(FB_MQTT_SSL_ERROR, error, str);
+ fb_mqtt_read_packet(mqtt); - /* Do not call purple_ssl_close() from the error_func */
- g_signal_emit_by_name(mqtt, "error", err);
+ g_signal_emit_by_name(mqtt, "open"); @@ -613,20 +662,29 @@
g_return_if_fail(FB_IS_MQTT(mqtt));
acc = purple_connection_get_account(priv->gc);
- priv->gsc = purple_ssl_connect(acc, host, port, fb_mqtt_cb_open,
- fb_mqtt_cb_open_error, mqtt);
+ client = purple_gio_socket_client_new(acc, &err); - if (priv->gsc == NULL) {
- fb_mqtt_cb_open_error(NULL, 0, mqtt);
+ fb_mqtt_take_error(mqtt, err, NULL); + priv->cancellable = g_cancellable_new(); + g_socket_client_set_tls(client, TRUE); + g_socket_client_connect_to_host_async(client, host, port, + priv->cancellable, fb_mqtt_cb_open, mqtt); + g_object_unref(client); @@ -662,7 +720,7 @@
g_return_val_if_fail(FB_IS_MQTT(mqtt), FALSE);
- connected = (priv->gsc != NULL) && priv->connected;
+ connected = (priv->conn != NULL) && priv->connected; if (!connected && error) {
fb_mqtt_error(mqtt, FB_MQTT_ERROR_GENERAL,
--- a/libpurple/protocols/facebook/mqtt.h Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/protocols/facebook/mqtt.h Sun Oct 30 12:03:44 2016 +0300
@@ -107,13 +107,6 @@
#define FB_MQTT_ERROR fb_mqtt_error_quark()
- * The #GQuark of the domain of MQTT SSL errors.
-#define FB_MQTT_SSL_ERROR fb_mqtt_ssl_error_quark()
typedef struct _FbMqtt FbMqtt;
typedef struct _FbMqttClass FbMqttClass;
typedef struct _FbMqttPrivate FbMqttPrivate;
@@ -298,16 +291,6 @@
fb_mqtt_error_quark(void);
- * fb_mqtt_ssl_error_quark:
- * Gets the #GQuark of the domain of MQTT SSL errors.
- * Returns: The #GQuark of the domain.
-fb_mqtt_ssl_error_quark(void);
* @gc: The #PurpleConnection.
--- a/libpurple/protocols/gg/Makefile.am Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/protocols/gg/Makefile.am Sun Oct 30 12:03:44 2016 +0300
@@ -3,64 +3,9 @@
-INTGG_LIBS = $(ZLIB_LIBS) $(GNUTLS_LIBS)
- -I$(top_srcdir)/libpurple/protocols/gg/lib \
@@ -137,7 +82,6 @@
-I$(top_srcdir)/libpurple \
-I$(top_builddir)/libpurple \
--- a/libpurple/protocols/gg/lib/COPYING Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,504 +0,0 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-[This is the first released version of the Lesser GPL. It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
- This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it. You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
- When we speak of free software, we are referring to freedom of use,
-not price. Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
- To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights. These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
- We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
- To protect each distributor, we want to make it very clear that
-there is no warranty for the free library. Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
- Finally, software patents pose a constant threat to the existence of
-any free program. We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder. Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
- Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License. This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License. We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
- When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library. The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom. The Lesser General
-Public License permits more lax criteria for linking other code with
- We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License. It also provides other free software developers Less
-of an advantage over competing non-free programs. These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries. However, the Lesser license provides advantages in certain
- For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard. To achieve this, non-free programs must be
-allowed to use the library. A more frequent case is that a free
-library does the same job as widely used non-free libraries. In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
- In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software. For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
- Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
- GNU LESSER GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
- 0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
- a) The modified work must itself be a software library.
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
- 6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
- b) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (1) uses at run time a
- copy of the library already present on the user's computer system,
- rather than copying library functions into the executable, and (2)
- will operate properly with a modified version of the library, if
- the user installs one, as long as the modified version is
- interface-compatible with the version that the work was made with.
- c) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
- d) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
- e) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- END OF TERMS AND CONDITIONS
- How to Apply These Terms to Your New Libraries
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
- <one line to give the library's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-Also add information on how to contact you by electronic and paper mail.
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary. Here is a sample; alter the names:
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
- <signature of Ty Coon>, 1 April 1990
- Ty Coon, President of Vice
-That's all there is to it!
--- a/libpurple/protocols/gg/lib/common.c Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,882 +0,0 @@
- * (C) Copyright 2001-2002 Wojtek Kaniewski <wojtekka@irc.pl>
- * Robert J. Woźny <speedy@ziew.org>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
- * \brief Funkcje wykorzystywane przez różne moduły biblioteki
-#ifndef GG_CONFIG_HAVE_VA_COPY
-# ifdef GG_CONFIG_HAVE___VA_COPY
-# define va_copy(dest, src) __va_copy((dest), (src))
-/* Taka wersja va_copy() działa poprawnie tylko na platformach, które
- * va_copy() de facto wcale nie potrzebują, np. MSVC. Definicja tylko dla
- * przejrzystości kodu. */
-# define va_copy(dest, src) (dest) = (src)
- * \internal Odpowiednik funkcji \c vsprintf alokujący miejsce na wynik.
- * Funkcja korzysta z funkcji \c vsnprintf, sprawdzając czy dostępna funkcja
- * systemowa jest zgodna ze standardem C99 czy wcześniejszymi.
- * \param format Format wiadomości (zgodny z \c printf)
- * \param ap Lista argumentów (zgodna z \c printf)
- * \return Zaalokowany bufor lub NULL, jeśli zabrakło pamięci.
-char *gg_vsaprintf(const char *format, va_list ap)
-#if !defined(GG_CONFIG_HAVE_C99_VSNPRINTF) && !defined(HAVE__VSCPRINTF)
- /* Jednak zachowanie zgodne z C99. */
- if (!(tmp = realloc(buf, size))) {
- res = vsnprintf(buf, size, format, aq);
- } while (res >= size || res < 0);
- size = _vscprintf(format, aq) + 1;
- /* libce Solarisa przy buforze NULL zawsze zwracają -1, więc
- * musimy podać coś istniejącego jako cel printf()owania. */
- size = vsnprintf(tmp, sizeof(tmp), format, aq) + 1;
- if (!(buf = malloc(size)))
- vsnprintf(buf, size, format, ap);
- * \internal Odpowiednik funkcji \c sprintf alokujący miejsce na wynik.
- * Funkcja korzysta z funkcji \c vsnprintf, sprawdzając czy dostępna funkcja
- * systemowa jest zgodna ze standardem C99 czy wcześniejszymi.
- * \param format Format wiadomości (zgodny z \c printf)
- * \return Zaalokowany bufor lub NULL, jeśli zabrakło pamięci.
-char *gg_saprintf(const char *format, ...)
- res = gg_vsaprintf(format, ap);
- * \internal Pobiera linię tekstu z bufora.
- * Funkcja niszczy bufor źródłowy bezpowrotnie, dzieląc go na kolejne ciągi
- * znaków i obcina znaki końca linii.
- * \param ptr Wskaźnik do zmiennej, która przechowuje aktualne położenie
- * w analizowanym buforze
- * \note Funkcja nie jest już używana. Pozostała dla zachowania ABI.
- * \return Wskaźnik do kolejnej linii tekstu lub NULL, jeśli to już koniec
-char *gg_get_line(char **ptr)
- if (!ptr || !*ptr || !strcmp(*ptr, ""))
- if (!(foo = strchr(*ptr, '\n')))
- if (len > 1 && res[len - 1] == '\r')
- * \internal Czyta linię tekstu z gniazda.
- * Funkcja czyta tekst znak po znaku, więc nie jest efektywna, ale dzięki
- * brakowi buforowania, nie koliduje z innymi funkcjami odczytu.
- * \note W przypadku zakończenia połączenia przez drugą stronę, ostatnia
- * linia nie jest zwracana.
- * \param sock Deskryptor gniazda
- * \param buf Wskaźnik do bufora
- * \param length Długość bufora
- * \return Zwraca wskaźnik na koniec odebranej linii jeśli się powiodło,
- * lub \c NULL w przypadku błędu.
-char *gg_read_line(int sock, char *buf, int length)
- if (!buf || length < 0)
- for (; length > 1; buf++, length--) {
- if ((ret = recv(sock, buf, 1, 0)) == -1 &&
- errno != EINTR && errno != EAGAIN)
- gg_debug(GG_DEBUG_MISC, "// gg_read_line() "
- "error on read (errno=%d, %s)\n",
- errno, strerror(errno));
- gg_debug(GG_DEBUG_MISC, "// gg_read_line() "
- } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
- * \internal Nawiązuje połączenie TCP.
- * \param addr Wskaźnik na strukturę \c in_addr z adresem serwera
- * \param port Port serwera
- * \param async Flaga asynchronicznego połączenia
- * \return Deskryptor gniazda lub -1 w przypadku błędu
-int gg_connect(void *addr, int port, int async)
- struct sockaddr_in sin;
- struct in_addr *a = addr;
- struct sockaddr_in myaddr;
- gg_debug(GG_DEBUG_FUNCTION, "** gg_connect(%s, %d, %d);\n",
- inet_ntoa(*a), port, async);
- if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
- gg_debug(GG_DEBUG_MISC, "// gg_connect() socket() failed "
- "(errno=%d, %s)\n", errno, strerror(errno));
- memset(&myaddr, 0, sizeof(myaddr));
- myaddr.sin_family = AF_INET;
- myaddr.sin_addr.s_addr = gg_local_ip;
- if (bind(sock, (struct sockaddr *) &myaddr, sizeof(myaddr)) == -1) {
- gg_debug(GG_DEBUG_MISC, "// gg_connect() bind() failed "
- "(errno=%d, %s)\n", errno, strerror(errno));
- if (!gg_fd_set_nonblocking(sock)) {
- gg_debug(GG_DEBUG_MISC, "// gg_connect() can't set "
- "nonblocking (errno=%d, %s)\n",
- errno, strerror(errno));
- memset(&sin, 0, sizeof(sin));
- sin.sin_port = htons(port);
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = a->s_addr;
- if (connect(sock, (struct sockaddr*) &sin, sizeof(sin)) == -1) {
- if (errno && (!async || errno != EINPROGRESS)) {
- gg_debug(GG_DEBUG_MISC, "// gg_connect() connect() "
- "failed (errno=%d, %s)\n",
- errno, strerror(errno));
- gg_debug(GG_DEBUG_MISC,
- "// gg_connect() connect() in progress\n");
- * \internal Usuwa znaki końca linii.
- * Funkcja działa bezpośrednio na buforze.
- * \param line Bufor z tekstem
-void gg_chomp(char *line)
- if (len > 0 && line[len - 1] == '\n')
- if (len > 0 && line[len - 1] == '\r')
- * \internal Koduje ciąg znaków do postacji adresu HTTP.
- * Zamienia znaki niedrukowalne, spoza ASCII i mające specjalne znaczenie
- * dla protokołu HTTP na encje postaci \c %XX, gdzie \c XX jest szesnastkową
- * \param str Ciąg znaków do zakodowania
- * \return Zaalokowany bufor lub \c NULL w przypadku błędu.
-char *gg_urlencode(const char *str)
- const char hex[] = "0123456789abcdef";
- for (p = str; *p; p++, size++) {
- if (!((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') ||
- (*p >= '0' && *p <= '9') || *p == ' ') || (*p == '@') ||
- (*p == '.') || (*p == '-'))
- if (!(buf = malloc(size + 1)))
- for (p = str, q = buf; *p; p++, q++) {
- if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') ||
- (*p >= '0' && *p <= '9') || (*p == '@') ||
- (*p == '.') || (*p == '-'))
- *q++ = hex[*p >> 4 & 15];
- * \internal Wyznacza skrót dla usług HTTP.
- * Funkcja jest wykorzystywana do wyznaczania skrótu adresu e-mail, hasła
- * i innych wartości przekazywanych jako parametry usług HTTP.
- * W parametrze \c format należy umieścić znaki określające postać kolejnych
- * parametrów: \c 's' jeśli parametr jest ciągiem znaków, \c 'u' jeśli jest
- * \param format Format kolejnych parametrów (niezgodny z \c printf)
- * \return Wartość skrótu
-int gg_http_hash(const char *format, ...)
- unsigned int a, c, i, j;
- for (j = 0; j < strlen(format); j++) {
- if (format[j] == 'u') {
- snprintf(buf, sizeof(buf), "%d", va_arg(ap, uin_t));
- if (!(arg = va_arg(ap, char*)))
- while ((c = (unsigned char) arg[i++]) != 0) {
- a = (c ^ b) + (c << 8);
- b = (a >> 24) | (a << 8);
- return (b < 0 ? -b : b);
- * \internal Zestaw znaków kodowania base64.
-static char gg_base64_charset[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
- * \internal Koduje ciąg znaków do base64.
- * Wynik funkcji należy zwolnić za pomocą \c free.
- * \param buf Bufor z danami do zakodowania
- * \return Zaalokowany bufor z zakodowanymi danymi
-char *gg_base64_encode(const char *buf)
- unsigned int i = 0, j = 0, k = 0, len = strlen(buf);
- res = out = malloc((len / 3 + 1) * 4 + 2);
- k = (buf[j] & 252) >> 2;
- k = ((buf[j] & 3) << 4) | ((buf[j + 1] & 240) >> 4);
- k = ((buf[j] & 15) << 2) | ((buf[j + 1] & 192) >> 6);
- k = (buf[j] & 15) << 2;
- *out++ = gg_base64_charset[k];
- for (j = 0; j < 4 - (i % 4); j++, out++)
- * \internal Dekoduje ciąg znaków zapisany w base64.
- * Wynik funkcji należy zwolnić za pomocą \c free.
- * \param buf Bufor źródłowy z danymi do zdekodowania
- * \return Zaalokowany bufor ze zdekodowanymi danymi
-char *gg_base64_decode(const char *buf)
- char *res, *save, *foo, val;
- save = res = calloc(1, (strlen(buf) / 4 + 1) * 3 + 2);
- end = buf + strlen(buf);
- while (*buf && buf < end) {
- if (*buf == '\r' || *buf == '\n') {
- if (!(foo = memchr(gg_base64_charset, *buf, sizeof(gg_base64_charset))))
- foo = gg_base64_charset;
- val = (int)(foo - gg_base64_charset);
- * \internal Tworzy nagłówek autoryzacji serwera pośredniczącego.
- * Dane pobiera ze zmiennych globalnych \c gg_proxy_username i
- * \c gg_proxy_password.
- * \return Zaalokowany bufor z tekstem lub NULL, jeśli serwer pośredniczący
- * nie jest używany lub nie wymaga autoryzacji.
-char *gg_proxy_auth(void)
- if (!gg_proxy_enabled || !gg_proxy_username || !gg_proxy_password)
- tmp_size = strlen(gg_proxy_username) + strlen(gg_proxy_password) + 2;
- tmp = malloc(tmp_size);
- snprintf(tmp, tmp_size, "%s:%s", gg_proxy_username, gg_proxy_password);
- enc = gg_base64_encode(tmp);
- out = malloc(strlen(enc) + 40);
- snprintf(out, strlen(enc) + 40, "Proxy-Authorization: Basic %s\r\n", enc);
- * \internal Tablica pomocnicza do wyznaczania sumy kontrolnej.
-static const uint32_t gg_crc32_table[256] =
- 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
- 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
- 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
- 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
- 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
- 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
- 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
- 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
- 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
- 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
- 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
- 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
- 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
- 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
- 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
- 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
- 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
- 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
- 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
- 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
- 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
- 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
- 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
- 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
- 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
- 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
- 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
- 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
- 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
- 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
- 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
- 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
- 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
- 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
- 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
- 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
- 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
- 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
- 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
- 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
- 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
- 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
- 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
- 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
- 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
- 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
- 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
- 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
- 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
- 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
- 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
- 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
- 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
- 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
- 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
- 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
- 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
- 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
- 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
- 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
- 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
- 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
- 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
- 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
- * Wyznacza sumę kontrolną CRC32.
- * \param crc Suma kontrola poprzedniego bloku danych lub 0 jeśli liczona
- * jest suma kontrolna pierwszego bloku
- * \param buf Bufor danych
- * \param len Długość bufora danych
- * \return Suma kontrolna.
-uint32_t gg_crc32(uint32_t crc, const unsigned char *buf, int len)
- if (buf == NULL || len < 0)
- crc = (crc >> 8) ^ gg_crc32_table[(crc ^ *buf++) & 0xff];
- return crc ^ 0xffffffffL;
- * \internal Parsuje identyfikator użytkownika.
- * \param str Ciąg tekstowy, zawierający identyfikator
- * \param len Długość identyfikatora
- * \return Identyfikator, lub 0, jeżeli nie udało się odczytać
-uin_t gg_str_to_uin(const char *str, int len)
- memcpy(buff, str, len);
- uin = strtoul(buff, &endptr, 10);
- if (errno == ERANGE || endptr[0] != '\0')
- * Szuka informacji o konferencji o podanym identyfikatorze.
- * \param sess Struktura sesji
- * \param id Identyfikator konferencji
- * \return Struktura z informacjami o konferencji
-gg_chat_list_t *gg_chat_find(struct gg_session *sess, uint64_t id)
- gg_chat_list_t *chat_list = sess->private_data->chat_list;
- while (chat_list != NULL) {
- if (chat_list->id == id)
- chat_list = chat_list->next;
- * \internal Aktualizuje informacje o konferencji.
- * \param sess Struktura sesji
- * \param id Identyfikator konferencji
- * \param version Wersja informacji o konferencji
- * \param participants Lista uczestników konferencji
- * \param participants_count Ilość uczestników konferencji
- * \return Wartość równa 0, jeżeli zakończono powodzeniem
-int gg_chat_update(struct gg_session *sess, uint64_t id, uint32_t version,
- const uin_t *participants, unsigned int participants_count)
- uin_t *participants_new;
- if (participants_count >= ~(unsigned int)0 / sizeof(uin_t))
- chat = gg_chat_find(sess, id);
- chat = malloc(sizeof(gg_chat_list_t));
- memset(chat, 0, sizeof(gg_chat_list_t));
- chat->next = sess->private_data->chat_list;
- sess->private_data->chat_list = chat;
- participants_new = realloc(chat->participants,
- sizeof(uin_t) * participants_count);
- if (participants_new == NULL)
- chat->version = version;
- chat->participants = participants_new;
- chat->participants_count = participants_count;
- memcpy(chat->participants, participants,
- sizeof(uin_t) * participants_count);
-void gg_connection_failure(struct gg_session *gs, struct gg_event *ge,
- enum gg_failure_t failure)
- ge->type = GG_EVENT_CONN_FAILED;
- ge->event.failure = failure;
- gs->state = GG_STATE_IDLE;
-time_t gg_server_time(struct gg_session *gs)
- time_t now = time(NULL);
- if (gs == NULL || gs->private_data == NULL) {
- gg_debug_session(gs, GG_DEBUG_ERROR, "time diff data is not "
- return now + gs->private_data->time_diff;
-void gg_strarr_free(char **strarr)
- for (it = strarr; *it != NULL; it++)
-char ** gg_strarr_dup(char **strarr)
- for (it = strarr; *it != NULL; it++)
- size = (len + 1) * sizeof(char*);
- gg_debug(GG_DEBUG_MISC | GG_DEBUG_ERROR, "// gg_strarr_dup() "
- "not enough memory for the array\n");
- for (i = 0; i < len; i++) {
- out[i] = strdup(strarr[i]);
- gg_debug(GG_DEBUG_MISC | GG_DEBUG_ERROR,
- "not enough memory for the array element\n");
- * c-indentation-style: k&r
- * indent-tabs-mode: notnil
--- a/libpurple/protocols/gg/lib/config.h Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/* Local libgadu configuration file. */
-/* libpurple's config */
-#define GG_LIBGADU_VERSION "1.12.1"
-/* Defined if libgadu was compiled for bigendian machine. */
-#undef GG_CONFIG_BIGENDIAN
-# define GG_CONFIG_BIGENDIAN
-/* Defined if this machine has gethostbyname_r(). */
-#undef GG_CONFIG_HAVE_GETHOSTBYNAME_R
-/* Define to 1 if you have the `_exit' function. */
-/* Defined if libgadu was compiled and linked with fork support. */
-#undef GG_CONFIG_HAVE_FORK
-# define GG_CONFIG_HAVE_FORK
-/* Defined if libgadu was compiled and linked with pthread support. */
-/* We don't use pthreads - they may not be safe. */
-#undef GG_CONFIG_HAVE_PTHREAD
-/* Defined if this machine has C99-compiliant vsnprintf(). */
-#undef HAVE_C99_VSNPRINTF
-#if !defined(_WIN32) || (defined(__MINGW64_VERSION_MAJOR) && __MINGW64_VERSION_MAJOR >= 3)
-# define HAVE_C99_VSNPRINTF
-/* Defined if this machine has va_copy(). */
-#define GG_CONFIG_HAVE_VA_COPY
-/* Defined if this machine has __va_copy(). */
-#define GG_CONFIG_HAVE___VA_COPY
-/* Defined if this machine supports long long. */
-#undef GG_CONFIG_HAVE_LONG_LONG
-# define GG_CONFIG_HAVE_LONG_LONG
-/* Defined if libgadu was compiled and linked with GnuTLS support. */
-#undef GG_CONFIG_HAVE_GNUTLS
-#if defined(HAVE_GNUTLS) && defined(HAVE_GNUTLS_2_10)
-# define GG_CONFIG_HAVE_GNUTLS
-/* Defined if libgadu was compiled and linked with OpenSSL support. */
-/* OpenSSL cannot be used with libpurple due to licence type. */
-#undef GG_CONFIG_HAVE_OPENSSL
-/* Defined if libgadu was compiled and linked with zlib support. */
-#define GG_CONFIG_HAVE_ZLIB
-/* Defined if uintX_t types are defined in <stdint.h>. */
-#undef GG_CONFIG_HAVE_STDINT_H
-# define GG_CONFIG_HAVE_STDINT_H
-/* Defined if uintX_t types are defined in <inttypes.h>. */
-#undef GG_CONFIG_HAVE_INTTYPES_H
-# define GG_CONFIG_HAVE_INTTYPES_H
-/* Defined if uintX_t types are defined in <sys/types.h>. */
-#undef GG_CONFIG_HAVE_SYS_TYPES_H
-# define GG_CONFIG_HAVE_SYS_TYPES_H
-/* Defined if this machine has uint64_t. */
-#define GG_CONFIG_HAVE_UINT64_T
-/* Defined if libgadu is GPL compliant (was not linked with OpenSSL or any
- * other non-GPL compliant library support). */
-#define GG_CONFIG_IS_GPL_COMPLIANT
-/* Defined if libgadu uses system defalt trusted CAs. */
-#define GG_CONFIG_SSL_SYSTEM_TRUST
-/* Defined if libgadu is GPL compliant (was not linked with OpenSSL or any
- other non-GPL compliant library support). */
-#define GG_CONFIG_IS_GPL_COMPLIANT
--- a/libpurple/protocols/gg/lib/dcc.c Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1410 +0,0 @@
- * (C) Copyright 2001-2008 Wojtek Kaniewski <wojtekka@irc.pl>
- * Tomasz Chiliński <chilek@chilan.com>
- * Adam Wysocki <gophi@ekg.chmurka.net>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
- * \brief Obsługa połączeń bezpośrednich do wersji Gadu-Gadu 6.x
- * \internal Przekazuje zawartość pakietu do odpluskwiania.
- * \param prefix Prefiks informacji
- * \param fd Deskryptor gniazda
- * \param buf Bufor z danumi
- * \param size Rozmiar bufora z danymi
-static void gg_dcc_debug_data(const char *prefix, int fd, const void *buf, unsigned int size)
- gg_debug(GG_DEBUG_MISC, "++ gg_dcc %s (fd=%d,len=%d)", prefix, fd, size);
- gg_debug_dump(NULL, GG_DEBUG_DUMP, buf, size);
- gg_debug(GG_DEBUG_MISC, "\n");
- * Wysyła żądanie zwrotnego połączenia bezpośredniego.
- * Funkcję wykorzystuje się, jeśli nie ma możliwości połączenia się z odbiorcą
- * pliku lub rozmowy głosowej. Po otrzymaniu żądania druga strona spróbuje
- * nawiązać zwrotne połączenie bezpośrednie z nadawcą.
- * \param sess Struktura sesji
- * \param uin Numer odbiorcy
- * \return Patrz \c gg_send_message_ctcp()
-int gg_dcc_request(struct gg_session *sess, uin_t uin)
- return gg_send_message_ctcp(sess, GG_CLASS_CTCP, uin, (const unsigned char*) "\002", 1);
- * \internal Zamienia znacznik czasu w postaci uniksowej na format API WIN32.
- * \note Funkcja działa jedynie gdy kompilator obsługuje typ danych
- * \param ut Czas w postaci uniksowej
- * \param ft Czas w postaci API WIN32
-static void gg_dcc_fill_filetime(uint32_t ut, uint32_t *ft)
- memcpy(ft, &tmp, sizeof(tmp));
- * Wypełnia pola struktury \c gg_dcc niezbędne do wysłania pliku.
- * \note Większą funkcjonalność zapewnia funkcja \c gg_dcc_fill_file_info2().
- * \param d Struktura połączenia
- * \param filename Nazwa pliku
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_dcc_fill_file_info(struct gg_dcc *d, const char *filename)
- return gg_dcc_fill_file_info2(d, filename, filename);
- * Wypełnia pola struktury \c gg_dcc niezbędne do wysłania pliku.
- * \param d Struktura połączenia
- * \param filename Nazwa pliku zapisywana w strukturze
- * \param local_filename Nazwa pliku w lokalnym systemie plików
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_dcc_fill_file_info2(struct gg_dcc *d, const char *filename, const char *local_filename)
- const char *name, *ext, *p;
- gg_debug(GG_DEBUG_FUNCTION, "** gg_dcc_fill_file_info2(%p, \"%s\", \"%s\");\n", d, filename, local_filename);
- if (!d || d->type != GG_SESSION_DCC_SEND) {
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() invalid arguments\n");
- if ((d->file_fd = open(local_filename, O_RDONLY)) == -1) {
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() open() failed (%s)\n", strerror(errno));
- if (fstat(d->file_fd, &st) == -1) {
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() "
- "fstat() failed (%s)\n", strerror(errno));
- if ((st.st_mode & S_IFDIR)) {
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() that's a directory\n");
- memset(&d->file_info, 0, sizeof(d->file_info));
- if (!(st.st_mode & S_IWUSR))
- d->file_info.mode |= gg_fix32(GG_DCC_FILEATTR_READONLY);
- gg_dcc_fill_filetime(st.st_atime, d->file_info.atime);
- gg_dcc_fill_filetime(st.st_mtime, d->file_info.mtime);
- gg_dcc_fill_filetime(st.st_ctime, d->file_info.ctime);
- d->file_info.size = gg_fix32(st.st_size);
- d->file_info.mode = gg_fix32(0x20); /* FILE_ATTRIBUTE_ARCHIVE */
- if (!(name = strrchr(filename, '/')))
- if (!(ext = strrchr(name, '.')))
- ext = name + strlen(name);
- for (i = 0, p = name; i < 8 && p < ext; i++, p++)
- d->file_info.short_filename[i] = toupper(name[i]);
- if (i == 8 && p < ext) {
- d->file_info.short_filename[6] = '~';
- d->file_info.short_filename[7] = '1';
- for (j = 0; *ext && j < 4; j++, p++)
- d->file_info.short_filename[i + j] = toupper(ext[j]);
- for (q = d->file_info.short_filename; *q; q++) {
- } else if (*q == 230) {
- } else if (*q == 234) {
- } else if (*q == 179) {
- } else if (*q == 241) {
- } else if (*q == 243) {
- } else if (*q == 156) {
- } else if (*q == 159) {
- } else if (*q == 191) {
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() short name \"%s\","
- " dos name \"%s\"\n", name, d->file_info.short_filename);
- strncpy((char*) d->file_info.filename, name, sizeof(d->file_info.filename) - 1);
- * \internal Rozpoczyna połączenie bezpośrednie z danym klientem.
- * \param ip Adres IP odbiorcy
- * \param port Port odbiorcy
- * \param my_uin Własny numer
- * \param peer_uin Numer odbiorcy
- * \param type Rodzaj połączenia (\c GG_SESSION_DCC_SEND lub \c GG_SESSION_DCC_GET)
- * \return Struktura \c gg_dcc lub \c NULL w przypadku błędu
-static struct gg_dcc *gg_dcc_transfer(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin, int type)
- struct gg_dcc *d = NULL;
- gg_debug(GG_DEBUG_FUNCTION, "** gg_dcc_transfer(%s, %d, %u, %u, "
- "%s);\n", inet_ntoa(addr), port, my_uin, peer_uin,
- (type == GG_SESSION_DCC_SEND) ? "SEND" : "GET");
- if (!ip || ip == INADDR_NONE || !port || !my_uin || !peer_uin) {
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_transfer() invalid arguments\n");
- if (!(d = (void*) calloc(1, sizeof(*d)))) {
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_transfer() not enough memory\n");
- d->check = GG_CHECK_WRITE;
- d->state = GG_STATE_CONNECTING;
- d->timeout = GG_DEFAULT_TIMEOUT;
- d->peer_uin = peer_uin;
- if ((d->fd = gg_connect(&addr, port, 1)) == -1) {
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_transfer() connection failed\n");
- * Rozpoczyna odbieranie pliku przez zwrotne połączenie bezpośrednie.
- * \param ip Adres IP nadawcy
- * \param port Port nadawcy
- * \param my_uin Własny numer
- * \param peer_uin Numer nadawcy
- * \return Struktura \c gg_dcc lub \c NULL w przypadku błędu
-struct gg_dcc *gg_dcc_get_file(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin)
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_get_file() handing over to gg_dcc_transfer()\n");
- return gg_dcc_transfer(ip, port, my_uin, peer_uin, GG_SESSION_DCC_GET);
- * Rozpoczyna wysyłanie pliku.
- * \param ip Adres IP odbiorcy
- * \param port Port odbiorcy
- * \param my_uin Własny numer
- * \param peer_uin Numer odbiorcy
- * \return Struktura \c gg_dcc lub \c NULL w przypadku błędu
-struct gg_dcc *gg_dcc_send_file(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin)
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_send_file() handing over to gg_dcc_transfer()\n");
- return gg_dcc_transfer(ip, port, my_uin, peer_uin, GG_SESSION_DCC_SEND);
- * Rozpoczyna połączenie głosowe.
- * \param ip Adres IP odbiorcy
- * \param port Port odbiorcy
- * \param my_uin Własny numer
- * \param peer_uin Numer odbiorcy
- * \return Struktura \c gg_dcc lub \c NULL w przypadku błędu
-struct gg_dcc *gg_dcc_voice_chat(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin)
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_voice_chat() handing over to gg_dcc_transfer()\n");
- return gg_dcc_transfer(ip, port, my_uin, peer_uin, GG_SESSION_DCC_VOICE);
- * Ustawia typ przychodzącego połączenia bezpośredniego.
- * Funkcję należy wywołać po otrzymaniu zdarzenia \c GG_EVENT_DCC_CALLBACK.
- * \param d Struktura połączenia
- * \param type Rodzaj połączenia (\c GG_SESSION_DCC_SEND lub
- * \c GG_SESSION_DCC_VOICE)
-void gg_dcc_set_type(struct gg_dcc *d, int type)
- d->state = (type == GG_SESSION_DCC_SEND) ? GG_STATE_SENDING_FILE_INFO : GG_STATE_SENDING_VOICE_REQUEST;
- * \internal Funkcja zwrotna połączenia bezpośredniego.
- * Pole \c callback struktury \c gg_dcc zawiera wskaźnik do tej funkcji.
- * Wywołuje ona \c gg_dcc_watch_fd() i zachowuje wynik w polu \c event.
- * \note Funkcjonalność funkcji zwrotnej nie jest już wspierana.
- * \param d Struktura połączenia
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-static int gg_dcc_callback(struct gg_dcc *d)
- struct gg_event *e = gg_dcc_watch_fd(d);
- return (e != NULL) ? 0 : -1;
- * Tworzy gniazdo nasłuchujące dla połączeń bezpośrednich.
- * Funkcja przywiązuje gniazdo do pierwszego wolnego portu TCP.
- * \param uin Własny numer
- * \param port Preferowany port (jeśli równy 0 lub -1, próbuje się domyślnego)
- * \note Ze względu na możliwość podania wartości -1 do parametru będącego
- * 16-bitową liczbą bez znaku, port 65535 nie jest dostępny.
- * \return Struktura \c gg_dcc lub \c NULL w przypadku błędu
-struct gg_dcc *gg_dcc_socket_create(uin_t uin, uint16_t port)
- int sock, bound = 0, errno2;
- gg_debug(GG_DEBUG_FUNCTION, "** gg_create_dcc_socket(%d, %d);\n", uin, port);
- gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() invalid arguments\n");
- if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
- gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() can't create socket (%s)\n", strerror(errno));
- if (port == 0 || port == (uint16_t)-1)
- port = GG_DEFAULT_DCC_PORT;
- struct sockaddr_in sin;
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = INADDR_ANY;
- sin.sin_port = htons(port);
- gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() trying port %d\n", port);
- if (!bind(sock, (struct sockaddr*) &sin, sizeof(sin)))
- gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() no free port found\n");
- if (listen(sock, 10)) {
- gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() unable to listen (%s)\n", strerror(errno));
- gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() bound to port %d\n", port);
- if (!(c = malloc(sizeof(*c)))) {
- gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() not enough memory for struct\n");
- memset(c, 0, sizeof(*c));
- c->port = c->id = port;
- c->type = GG_SESSION_DCC_SOCKET;
- c->state = GG_STATE_LISTENING;
- c->check = GG_CHECK_READ;
- c->callback = gg_dcc_callback;
- c->destroy = gg_dcc_free;
- * Wysyła ramkę danych połączenia głosowego.
- * \param d Struktura połączenia
- * \param buf Bufor z danymi
- * \param length Długość bufora z danymi
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_dcc_voice_send(struct gg_dcc *d, char *buf, int length)
- struct packet_s packet;
- gg_debug(GG_DEBUG_FUNCTION, "++ gg_dcc_voice_send(%p, %p, %d);\n", d, buf, length);
- if (!d || !buf || length < 0 || d->type != GG_SESSION_DCC_VOICE) {
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_voice_send() invalid argument\n");
- packet.type = 0x03; /* XXX */
- packet.length = gg_fix32(length);
- if (send(d->fd, &packet, sizeof(packet), 0) < (signed)sizeof(packet)) {
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_voice_send() send() failed\n");
- gg_dcc_debug_data("write", d->fd, &packet, sizeof(packet));
- if (send(d->fd, buf, length, 0) < length) {
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_voice_send() send() failed\n");
- gg_dcc_debug_data("write", d->fd, buf, length);
- * \internal Odbiera dane z połączenia bezpośredniego z obsługą błędów.
- * \param fd Deskryptor gniazda
- * \param buf Bufor na dane
- * \param size Rozmiar bufora na dane
-#define gg_dcc_read(fd, buf, size) \
- int _tmp = recv(fd, buf, size, 0); \
- if (_tmp < (int) size) { \
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() recv() failed " \
- "(errno=%d, %s)\n", errno, strerror(errno)); \
- } else if (_tmp == 0) { \
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() recv() failed, " \
- "connection broken\n"); \
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() recv() failed " \
- "(%d bytes, %" GG_SIZE_FMT " needed)\n", \
- e->type = GG_EVENT_DCC_ERROR; \
- e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE; \
- gg_dcc_debug_data("read", fd, buf, size); \
- * \internal Wysyła dane do połączenia bezpośredniego z obsługą błędów.
- * \param fd Deskryptor gniazda
- * \param buf Bufor z danymi
- * \param size Rozmiar bufora z danymi
-#define gg_dcc_write(fd, buf, size) \
- gg_dcc_debug_data("write", fd, buf, size); \
- write_res = send(fd, buf, size, 0); \
- if (write_res < (int) size) { \
- if (write_res == -1) { \
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() send() " \
- "failed (errno=%d, %s)\n", errno, strerror(errno)); \
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() send() " \
- "failed (%" GG_SIZE_FMT " needed, %d done)\n", \
- e->type = GG_EVENT_DCC_ERROR; \
- e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE; \
- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
- * Funkcja zwraca strukturę zdarzenia \c gg_event. Jeśli rodzaj zdarzenia
- * to \c GG_EVENT_NONE, nie wydarzyło się jeszcze nic wartego odnotowania.
- * Strukturę zdarzenia należy zwolnić funkcja \c gg_event_free.
- * \param h Struktura połączenia
- * \return Struktura zdarzenia lub \c NULL jeśli wystąpił błąd
-struct gg_event *gg_dcc_watch_fd(struct gg_dcc *h)
- gg_debug(GG_DEBUG_FUNCTION, "** gg_dcc_watch_fd(%p);\n", h);
- if (!h || (h->type != GG_SESSION_DCC &&
- h->type != GG_SESSION_DCC_SOCKET &&
- h->type != GG_SESSION_DCC_SEND &&
- h->type != GG_SESSION_DCC_GET &&
- h->type != GG_SESSION_DCC_VOICE))
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() invalid argument\n");
- if (!(e = (void*) calloc(1, sizeof(*e)))) {
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() not enough memory\n");
- e->type = GG_EVENT_NONE;
- if (h->type == GG_SESSION_DCC_SOCKET) {
- struct sockaddr_in sin;
- socklen_t sin_len = sizeof(sin);
- if ((fd = accept(h->fd, (struct sockaddr*) &sin, &sin_len)) == -1) {
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() can't "
- "accept() new connection (errno=%d, %s)\n",
- errno, strerror(errno));
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() new direct "
- "connection from %s:%d\n", inet_ntoa(sin.sin_addr),
- if (!gg_fd_set_nonblocking(fd)) {
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() can't set"
- " nonblocking (errno=%d, %s)\n",
- errno, strerror(errno));
- e->type = GG_EVENT_DCC_ERROR;
- e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE;
- if (!(c = (void*) calloc(1, sizeof(*c)))) {
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() not enough memory for client data\n");
- c->check = GG_CHECK_READ;
- c->state = GG_STATE_READING_UIN_1;
- c->type = GG_SESSION_DCC;
- c->timeout = GG_DEFAULT_TIMEOUT;
- c->remote_addr = sin.sin_addr.s_addr;
- c->remote_port = ntohs(sin.sin_port);
- e->type = GG_EVENT_DCC_NEW;
- struct gg_dcc_tiny_packet tiny_pkt;
- struct gg_dcc_small_packet small_pkt;
- struct gg_dcc_big_packet big_pkt;
- socklen_t res_size = sizeof(res);
- char buf[1024], ack[] = "UDAG";
- struct gg_dcc_file_info_packet {
- struct gg_dcc_big_packet big;
- struct gg_file_info file_info;
- struct gg_dcc_file_info_packet file_info_packet;
- case GG_STATE_READING_UIN_1:
- case GG_STATE_READING_UIN_2:
- gg_debug(GG_DEBUG_MISC,
- "// gg_dcc_watch_fd() GG_READING_UIN_%d\n",
- (h->state == GG_STATE_READING_UIN_1) ? 1 : 2);
- gg_dcc_read(h->fd, &uin, sizeof(uin));
- if (h->state == GG_STATE_READING_UIN_1) {
- h->state = GG_STATE_READING_UIN_2;
- h->check = GG_CHECK_READ;
- h->timeout = GG_DEFAULT_TIMEOUT;
- h->peer_uin = gg_fix32(uin);
- h->state = GG_STATE_SENDING_ACK;
- h->check = GG_CHECK_WRITE;
- h->timeout = GG_DEFAULT_TIMEOUT;
- h->uin = gg_fix32(uin);
- e->type = GG_EVENT_DCC_CLIENT_ACCEPT;
- case GG_STATE_SENDING_ACK:
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_SENDING_ACK\n");
- gg_dcc_write(h->fd, ack, (size_t)4);
- h->state = GG_STATE_READING_TYPE;
- h->check = GG_CHECK_READ;
- h->timeout = GG_DEFAULT_TIMEOUT;
- case GG_STATE_READING_TYPE:
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_TYPE\n");
- gg_dcc_read(h->fd, &small_pkt, sizeof(small_pkt));
- small_pkt.type = gg_fix32(small_pkt.type);
- switch (small_pkt.type) {
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() callback\n");
- h->type = GG_SESSION_DCC_SEND;
- h->state = GG_STATE_SENDING_FILE_INFO;
- h->check = GG_CHECK_WRITE;
- h->timeout = GG_DEFAULT_TIMEOUT;
- e->type = GG_EVENT_DCC_CALLBACK;
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() dialin\n");
- h->type = GG_SESSION_DCC_GET;
- h->state = GG_STATE_READING_REQUEST;
- h->check = GG_CHECK_READ;
- h->timeout = GG_DEFAULT_TIMEOUT;
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() unknown dcc type "
- "(%.4x) from %u\n", small_pkt.type, h->peer_uin);
- e->type = GG_EVENT_DCC_ERROR;
- e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE;
- case GG_STATE_READING_REQUEST:
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_REQUEST\n");
- gg_dcc_read(h->fd, &small_pkt, sizeof(small_pkt));
- small_pkt.type = gg_fix32(small_pkt.type);
- switch (small_pkt.type) {
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() file transfer request\n");
- h->state = GG_STATE_READING_FILE_INFO;
- h->check = GG_CHECK_READ;
- h->timeout = GG_DEFAULT_TIMEOUT;
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() voice chat request\n");
- h->state = GG_STATE_SENDING_VOICE_ACK;
- h->check = GG_CHECK_WRITE;
- h->timeout = GG_DCC_TIMEOUT_VOICE_ACK;
- h->type = GG_SESSION_DCC_VOICE;
- e->type = GG_EVENT_DCC_NEED_VOICE_ACK;
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() unknown "
- "dcc request (%.4x) from %u\n",
- small_pkt.type, h->peer_uin);
- e->type = GG_EVENT_DCC_ERROR;
- e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE;
- case GG_STATE_READING_FILE_INFO:
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_FILE_INFO\n");
- gg_dcc_read(h->fd, &file_info_packet, sizeof(file_info_packet));
- memcpy(&h->file_info, &file_info_packet.file_info, sizeof(h->file_info));
- h->file_info.mode = gg_fix32(h->file_info.mode);
- h->file_info.size = gg_fix32(h->file_info.size);
- h->state = GG_STATE_SENDING_FILE_ACK;
- h->check = GG_CHECK_WRITE;
- h->timeout = GG_DCC_TIMEOUT_FILE_ACK;
- e->type = GG_EVENT_DCC_NEED_FILE_ACK;
- case GG_STATE_SENDING_FILE_ACK:
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_FILE_ACK\n");
- big_pkt.type = gg_fix32(0x0006); /* XXX */
- big_pkt.dunno1 = gg_fix32(h->offset);
- gg_dcc_write(h->fd, &big_pkt, sizeof(big_pkt));
- h->state = GG_STATE_READING_FILE_HEADER;
- h->chunk_size = sizeof(big_pkt);
- tmp_buf = malloc(sizeof(big_pkt));
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() out of memory\n");
- h->chunk_buf = tmp_buf;
- h->check = GG_CHECK_READ;
- h->timeout = GG_DEFAULT_TIMEOUT;
- case GG_STATE_SENDING_VOICE_ACK:
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_VOICE_ACK\n");
- tiny_pkt.type = 0x01; /* XXX */
- gg_dcc_write(h->fd, &tiny_pkt, sizeof(tiny_pkt));
- h->state = GG_STATE_READING_VOICE_HEADER;
- h->check = GG_CHECK_READ;
- h->timeout = GG_DEFAULT_TIMEOUT;
- case GG_STATE_READING_FILE_HEADER:
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_FILE_HEADER\n");
- tmp = recv(h->fd, h->chunk_buf + h->chunk_offset, h->chunk_size - h->chunk_offset, 0);
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() recv() "
- "failed (errno=%d, %s)\n", errno, strerror(errno));
- e->type = GG_EVENT_DCC_ERROR;
- e->event.dcc_error = GG_ERROR_DCC_NET;
- gg_dcc_debug_data("read", h->fd,
- h->chunk_buf + h->chunk_offset,
- h->chunk_size - h->chunk_offset);
- h->chunk_offset += tmp;
- if (h->chunk_offset < h->chunk_size)
- memcpy(&big_pkt, h->chunk_buf, sizeof(big_pkt));
- big_pkt.type = gg_fix32(big_pkt.type);
- h->chunk_size = gg_fix32(big_pkt.dunno1);
- if (big_pkt.type == 0x0005) { /* XXX */
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() transfer refused\n");
- e->type = GG_EVENT_DCC_ERROR;
- e->event.dcc_error = GG_ERROR_DCC_REFUSED;
- if (h->chunk_size == 0) {
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() empty chunk, EOF\n");
- e->type = GG_EVENT_DCC_DONE;
- h->state = GG_STATE_GETTING_FILE;
- h->check = GG_CHECK_READ;
- h->timeout = GG_DEFAULT_TIMEOUT;
- case GG_STATE_READING_VOICE_HEADER:
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_VOICE_HEADER\n");
- gg_dcc_read(h->fd, &tiny_pkt, sizeof(tiny_pkt));
- switch (tiny_pkt.type) {
- h->state = GG_STATE_READING_VOICE_SIZE;
- h->check = GG_CHECK_READ;
- h->timeout = GG_DEFAULT_TIMEOUT;
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() "
- "peer breaking connection\n");
- /* XXX zwracać odpowiedni event */
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() "
- "unknown request (%.2x)\n", tiny_pkt.type);
- e->type = GG_EVENT_DCC_ERROR;
- e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE;
- case GG_STATE_READING_VOICE_SIZE:
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_VOICE_SIZE\n");
- gg_dcc_read(h->fd, &small_pkt, sizeof(small_pkt));
- small_pkt.type = gg_fix32(small_pkt.type);
- if (small_pkt.type < 16 || small_pkt.type > sizeof(buf)) {
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() "
- "invalid voice frame size (%d)\n", small_pkt.type);
- e->type = GG_EVENT_DCC_ERROR;
- e->event.dcc_error = GG_ERROR_DCC_NET;
- h->chunk_size = small_pkt.type;
- if (!(h->voice_buf = malloc(h->chunk_size))) {
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() out of memory for voice frame\n");
- h->state = GG_STATE_READING_VOICE_DATA;
- h->check = GG_CHECK_READ;
- h->timeout = GG_DEFAULT_TIMEOUT;
- case GG_STATE_READING_VOICE_DATA:
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_VOICE_DATA\n");
- tmp = recv(h->fd, h->voice_buf + h->chunk_offset, h->chunk_size - h->chunk_offset, 0);
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() "
- "recv() failed (errno=%d, %s)\n",
- errno, strerror(errno));
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() "
- "recv() failed, connection broken\n");
- e->type = GG_EVENT_DCC_ERROR;
- e->event.dcc_error = GG_ERROR_DCC_NET;
- gg_dcc_debug_data("read", h->fd, h->voice_buf + h->chunk_offset, tmp);
- h->chunk_offset += tmp;
- if (h->chunk_offset >= h->chunk_size) {
- e->type = GG_EVENT_DCC_VOICE_DATA;
- e->event.dcc_voice_data.data = (unsigned char*) h->voice_buf;
- e->event.dcc_voice_data.length = h->chunk_size;
- h->state = GG_STATE_READING_VOICE_HEADER;
- h->check = GG_CHECK_READ;
- h->timeout = GG_DEFAULT_TIMEOUT;
- case GG_STATE_CONNECTING:
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_CONNECTING\n");
- if ((foo = getsockopt(h->fd, SOL_SOCKET, SO_ERROR, &res, &res_size)) || res) {
- gg_debug(GG_DEBUG_MISC,
- "// gg_dcc_watch_fd() connection failed "
- "(fd=%d,errno=%d(%s),foo=%d,res=%d(%s))\n",
- h->fd, errno, strerror(errno), foo, res, strerror(res));
- e->type = GG_EVENT_DCC_ERROR;
- e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE;
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() connected, sending uins\n");
- uins[0] = gg_fix32(h->uin);
- uins[1] = gg_fix32(h->peer_uin);
- gg_dcc_write(h->fd, uins, sizeof(uins));
- h->state = GG_STATE_READING_ACK;
- h->check = GG_CHECK_READ;
- h->timeout = GG_DEFAULT_TIMEOUT;
- case GG_STATE_READING_ACK:
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_ACK\n");
- gg_dcc_read(h->fd, buf, (size_t)4);
- if (strncmp(buf, ack, 4)) {
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() did't get ack\n");
- e->type = GG_EVENT_DCC_ERROR;
- e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE;
- h->check = GG_CHECK_WRITE;
- h->timeout = GG_DEFAULT_TIMEOUT;
- h->state = GG_STATE_SENDING_REQUEST;
- case GG_STATE_SENDING_VOICE_REQUEST:
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_VOICE_REQUEST\n");
- small_pkt.type = gg_fix32(0x0003);
- gg_dcc_write(h->fd, &small_pkt, sizeof(small_pkt));
- h->state = GG_STATE_READING_VOICE_ACK;
- h->check = GG_CHECK_READ;
- h->timeout = GG_DEFAULT_TIMEOUT;
- case GG_STATE_SENDING_REQUEST:
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_REQUEST\n");
- small_pkt.type = (h->type == GG_SESSION_DCC_GET) ?
- gg_fix32(0x0003) : gg_fix32(0x0002); /* XXX */
- gg_dcc_write(h->fd, &small_pkt, sizeof(small_pkt));
- case GG_SESSION_DCC_GET:
- h->state = GG_STATE_READING_REQUEST;
- h->check = GG_CHECK_READ;
- h->timeout = GG_DEFAULT_TIMEOUT;
- case GG_SESSION_DCC_SEND:
- h->state = GG_STATE_SENDING_FILE_INFO;
- h->check = GG_CHECK_WRITE;
- h->timeout = GG_DEFAULT_TIMEOUT;
- e->type = GG_EVENT_DCC_NEED_FILE_INFO;
- case GG_SESSION_DCC_VOICE:
- h->state = GG_STATE_SENDING_VOICE_REQUEST;
- h->check = GG_CHECK_WRITE;
- h->timeout = GG_DEFAULT_TIMEOUT;
- case GG_STATE_SENDING_FILE_INFO:
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_FILE_INFO\n");
- if (h->file_fd == -1) {
- e->type = GG_EVENT_DCC_NEED_FILE_INFO;
- small_pkt.type = gg_fix32(0x0001); /* XXX */
- gg_dcc_write(h->fd, &small_pkt, sizeof(small_pkt));
- file_info_packet.big.type = gg_fix32(0x0003); /* XXX */
- file_info_packet.big.dunno1 = 0;
- file_info_packet.big.dunno2 = 0;
- memcpy(&file_info_packet.file_info, &h->file_info, sizeof(h->file_info));
- /* zostają teraz u nas, więc odwracamy z powrotem */
- h->file_info.size = gg_fix32(h->file_info.size);
- h->file_info.mode = gg_fix32(h->file_info.mode);
- gg_dcc_write(h->fd, &file_info_packet, sizeof(file_info_packet));
- h->state = GG_STATE_READING_FILE_ACK;
- h->check = GG_CHECK_READ;
- h->timeout = GG_DCC_TIMEOUT_FILE_ACK;
- case GG_STATE_READING_FILE_ACK:
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_FILE_ACK\n");
- gg_dcc_read(h->fd, &big_pkt, sizeof(big_pkt));
- /* XXX sprawdzać wynik */
- h->offset = gg_fix32(big_pkt.dunno1);
- h->state = GG_STATE_SENDING_FILE_HEADER;
- h->check = GG_CHECK_WRITE;
- h->timeout = GG_DEFAULT_TIMEOUT;
- e->type = GG_EVENT_DCC_ACK;
- case GG_STATE_READING_VOICE_ACK:
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_VOICE_ACK\n");
- gg_dcc_read(h->fd, &tiny_pkt, sizeof(tiny_pkt));
- if (tiny_pkt.type != 0x01) {
- gg_debug(GG_DEBUG_MISC, "// invalid "
- "reply (%.2x), connection "
- "refused\n", tiny_pkt.type);
- e->type = GG_EVENT_DCC_ERROR;
- e->event.dcc_error = GG_ERROR_DCC_REFUSED;
- h->state = GG_STATE_READING_VOICE_HEADER;
- h->check = GG_CHECK_READ;
- h->timeout = GG_DEFAULT_TIMEOUT;
- e->type = GG_EVENT_DCC_ACK;
- case GG_STATE_SENDING_FILE_HEADER:
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_FILE_HEADER\n");
- if ((h->chunk_size = h->file_info.size - h->offset) > 4096) {
- big_pkt.type = gg_fix32(0x0003); /* XXX */
- big_pkt.type = gg_fix32(0x0002); /* XXX */
- big_pkt.dunno1 = gg_fix32(h->chunk_size);
- gg_dcc_write(h->fd, &big_pkt, sizeof(big_pkt));
- h->state = GG_STATE_SENDING_FILE;
- h->check = GG_CHECK_WRITE;
- h->timeout = GG_DEFAULT_TIMEOUT;
- case GG_STATE_SENDING_FILE:
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_FILE\n");
- if ((utmp = h->chunk_size - h->chunk_offset) > sizeof(buf))
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() "
- "offset=%d, size=%d\n",
- h->offset, h->file_info.size);
- if (h->file_info.size == 0) {
- gg_debug(GG_DEBUG_MISC,
- "// gg_dcc_watch_fd() read()"
- "reached eof on empty file\n");
- e->type = GG_EVENT_DCC_DONE;
- if (h->offset >= h->file_info.size) {
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() offset >= size, finished\n");
- e->type = GG_EVENT_DCC_DONE;
- if (lseek(h->file_fd, h->offset, SEEK_SET) != (off_t)h->offset) {
- gg_debug(GG_DEBUG_MISC,
- "// gg_dcc_watch_fd() lseek() "
- "failed. (errno=%d, %s)\n",
- errno, strerror(errno));
- e->type = GG_EVENT_DCC_ERROR;
- e->event.dcc_error = GG_ERROR_DCC_FILE;
- size = read(h->file_fd, buf, utmp);
- gg_debug(GG_DEBUG_MISC,
- "// gg_dcc_watch_fd() read() "
- "failed. (errno=%d, %s)\n",
- errno, strerror(errno));
- e->type = GG_EVENT_DCC_ERROR;
- e->event.dcc_error = GG_ERROR_DCC_FILE;
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() reached eof\n");
- e->type = GG_EVENT_DCC_ERROR;
- e->event.dcc_error = GG_ERROR_DCC_EOF;
- /* jeśli wczytaliśmy więcej, utnijmy. */
- if (h->offset + size > h->file_info.size) {
- gg_debug(GG_DEBUG_MISC,
- "// gg_dcc_watch_fd() read() "
- "too much (read=%d, ofs=%d, "
- "size=%d)\n", size, h->offset,
- size = h->file_info.size - h->offset;
- gg_debug(GG_DEBUG_MISC,
- "// gg_dcc_watch_fd() "
- "reached EOF after cutting\n");
- e->type = GG_EVENT_DCC_DONE;
- tmp = send(h->fd, buf, size, 0);
- gg_debug(GG_DEBUG_MISC,
- "// gg_dcc_watch_fd() send() "
- "failed (%s)\n", strerror(errno));
- e->type = GG_EVENT_DCC_ERROR;
- e->event.dcc_error = GG_ERROR_DCC_NET;
- gg_debug(GG_DEBUG_MISC,
- "// gg_dcc_watch_fd() send() "
- "failed (connection reset)\n");
- e->type = GG_EVENT_DCC_ERROR;
- e->event.dcc_error = GG_ERROR_DCC_NET;
- if (h->offset >= h->file_info.size) {
- e->type = GG_EVENT_DCC_DONE;
- h->chunk_offset += tmp;
- if (h->chunk_offset >= h->chunk_size) {
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() chunk finished\n");
- h->state = GG_STATE_SENDING_FILE_HEADER;
- h->timeout = GG_DEFAULT_TIMEOUT;
- h->state = GG_STATE_SENDING_FILE;
- h->timeout = GG_DCC_TIMEOUT_SEND;
- h->check = GG_CHECK_WRITE;
- case GG_STATE_GETTING_FILE:
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_GETTING_FILE\n");
- if ((utmp = h->chunk_size - h->chunk_offset) > sizeof(buf))
- if (h->offset >= h->file_info.size) {
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() offset >= size, finished\n");
- e->type = GG_EVENT_DCC_DONE;
- size = recv(h->fd, buf, utmp, 0);
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() "
- "ofs=%d, size=%d, recv()=%d\n",
- h->offset, h->file_info.size, size);
- gg_debug(GG_DEBUG_MISC,
- "// gg_dcc_watch_fd() recv() "
- "failed. (errno=%d, %s)\n",
- errno, strerror(errno));
- e->type = GG_EVENT_DCC_ERROR;
- e->event.dcc_error = GG_ERROR_DCC_NET;
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() recv() reached eof\n");
- e->type = GG_EVENT_DCC_ERROR;
- e->event.dcc_error = GG_ERROR_DCC_EOF;
- tmp = write(h->file_fd, buf, size);
- if (tmp == -1 || tmp < size) {
- gg_debug(GG_DEBUG_MISC,
- "// gg_dcc_watch_fd() write() "
- "failed (%d:fd=%d:res=%d:%s)\n",
- e->type = GG_EVENT_DCC_ERROR;
- e->event.dcc_error = GG_ERROR_DCC_NET;
- if (h->offset >= h->file_info.size) {
- e->type = GG_EVENT_DCC_DONE;
- h->chunk_offset += size;
- if (h->chunk_offset >= h->chunk_size) {
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() chunk finished\n");
- h->state = GG_STATE_READING_FILE_HEADER;
- h->timeout = GG_DEFAULT_TIMEOUT;
- h->chunk_size = sizeof(big_pkt);
- tmp_buf = malloc(sizeof(big_pkt));
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() out of memory\n");
- h->chunk_buf = tmp_buf;
- h->state = GG_STATE_GETTING_FILE;
- h->timeout = GG_DCC_TIMEOUT_GET;
- h->check = GG_CHECK_READ;
- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_???\n");
- e->type = GG_EVENT_DCC_ERROR;
- e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE;
- * Zwalnia zasoby używane przez połączenie bezpośrednie.
- * \param d Struktura połączenia
-void gg_dcc_free(struct gg_dcc *d)
- gg_debug(GG_DEBUG_FUNCTION, "** gg_dcc_free(%p);\n", d);
- gg_file_close(d->file_fd);
- * c-indentation-style: k&r
- * indent-tabs-mode: notnil
--- a/libpurple/protocols/gg/lib/dcc7.c Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1660 +0,0 @@
- * (C) Copyright 2001-2010 Wojtek Kaniewski <wojtekka@irc.pl>
- * Tomasz Chiliński <chilek@chilan.com>
- * Adam Wysocki <gophi@ekg.chmurka.net>
- * Bartłomiej Zimoń <uzi18@o2.pl>
- * Thanks to Jakub Zawadzki <darkjames@darkjames.ath.cx>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110,
- * \brief Obsługa połączeń bezpośrednich od wersji Gadu-Gadu 7.x
-# define gg_debug_dcc(dcc, level, fmt, ...) \
- gg_debug_session(((dcc) != NULL) ? (dcc)->sess : NULL, level, fmt, __VA_ARGS__)
-# define gg_debug_dcc(dcc, level, fmt...) \
- gg_debug_session(((dcc) != NULL) ? (dcc)->sess : NULL, level, fmt)
-#define gg_debug_dump_dcc(dcc, level, buf, len) \
- gg_debug_dump(((dcc) != NULL) ? (dcc)->sess : NULL, level, buf, len)
- * \internal Dodaje połączenie bezpośrednie do sesji.
- * \param sess Struktura sesji
- * \param dcc Struktura połączenia
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-static int gg_dcc7_session_add(struct gg_session *sess, struct gg_dcc7 *dcc)
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_session_add(%p, %p)\n", sess, dcc);
- if (!sess || !dcc || dcc->next) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_session_add() invalid parameters\n");
- dcc->next = sess->dcc7_list;
- * \internal Usuwa połączenie bezpośrednie z sesji.
- * \param sess Struktura sesji
- * \param dcc Struktura połączenia
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-static int gg_dcc7_session_remove(struct gg_session *sess, struct gg_dcc7 *dcc)
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_session_remove(%p, %p)\n", sess, dcc);
- if (sess == NULL || dcc == NULL) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_session_remove() invalid parameters\n");
- if (sess->dcc7_list == dcc) {
- sess->dcc7_list = dcc->next;
- for (tmp = sess->dcc7_list; tmp != NULL; tmp = tmp->next) {
- if (tmp->next == dcc) {
- * \internal Zwraca strukturę połączenia o danym identyfikatorze.
- * \param sess Struktura sesji
- * \param id Identyfikator połączenia
- * \param uin Numer nadawcy lub odbiorcy
- * \return Struktura połączenia lub \c NULL jeśli nie znaleziono
-static struct gg_dcc7 *gg_dcc7_session_find(struct gg_session *sess, gg_dcc7_id_t id, uin_t uin)
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_session_find(%p, ..., %d)\n", sess, (int) uin);
- empty = !memcmp(&id, "\0\0\0\0\0\0\0\0", 8);
- for (tmp = sess->dcc7_list; tmp; tmp = tmp->next) {
- if (tmp->peer_uin == uin && tmp->state == GG_STATE_WAITING_FOR_ACCEPT)
- if (!memcmp(&tmp->cid, &id, sizeof(id)))
- * \internal Rozpoczyna proces pobierania adresu
- * \param dcc Struktura połączenia
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-static int gg_dcc7_get_relay_addr(struct gg_dcc7 *dcc)
- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_get_relay_addr(%p)\n", dcc);
- if (dcc == NULL || dcc->sess == NULL) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_get_relay_addr() invalid parameters\n");
- if (dcc->sess->resolver_start(&dcc->fd, &dcc->resolver, GG_RELAY_HOST) == -1) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_get_relay_addr() "
- "resolving failed (errno=%d, %s)\n",
- errno, strerror(errno));
- dcc->state = GG_STATE_RESOLVING_RELAY;
- dcc->check = GG_CHECK_READ;
- dcc->timeout = GG_DEFAULT_TIMEOUT;
- * \internal Nawiązuje połączenie bezpośrednie
- * \param dcc Struktura połączenia
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-static int gg_dcc7_connect(struct gg_dcc7 *dcc)
- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_connect(%p)\n", dcc);
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_connect() invalid parameters\n");
- if ((dcc->fd = gg_connect(&dcc->remote_addr, dcc->remote_port, 1)) == -1) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_connect() connection failed\n");
- dcc->state = GG_STATE_CONNECTING;
- dcc->check = GG_CHECK_WRITE;
- dcc->timeout = GG_DCC7_TIMEOUT_CONNECT;
- * \internal Tworzy gniazdo nasłuchujące dla połączenia bezpośredniego
- * \param dcc Struktura połączenia
- * \param addr Preferowany adres (jeśli równy 0, nasłuchujemy na wszystkich interfejsach)
- * \param port Preferowany port (jeśli równy 0, nasłuchujemy na losowym)
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-static int gg_dcc7_listen(struct gg_dcc7 *dcc, uint32_t addr, uint16_t port)
- struct sockaddr_in sin;
- socklen_t sin_len = sizeof(sin);
- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_listen(%p, %d)\n", dcc, port);
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_listen() invalid parameters\n");
- if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_listen() can't create socket (%s)\n", strerror(errno));
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = addr;
- sin.sin_port = htons(port);
- if (bind(fd, (struct sockaddr*) &sin, sizeof(sin)) == -1) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_listen() unable to"
- " bind to %s:%d\n", inet_ntoa(sin.sin_addr), port);
- if (port == 0 && getsockname(fd, (struct sockaddr*) &sin, &sin_len) == -1) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_listen() unable to bind to port %d\n", port);
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_listen() unable to listen (%s)\n", strerror(errno));
- dcc->local_addr = sin.sin_addr.s_addr;
- dcc->local_port = ntohs(sin.sin_port);
- dcc->state = GG_STATE_LISTENING;
- dcc->check = GG_CHECK_READ;
- dcc->timeout = GG_DCC7_TIMEOUT_FILE_ACK;
- * \internal Tworzy gniazdo nasłuchujące i wysyła jego parametry
- * \param dcc Struktura połączenia
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-static int gg_dcc7_listen_and_send_info(struct gg_dcc7 *dcc)
- struct gg_dcc7_info pkt;
- uint16_t external_port;
- uint32_t external_addr;
- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_listen_and_send_info(%p)\n", dcc);
- if (gg_dcc7_listen(dcc, dcc->sess->client_addr, dcc->sess->client_port) == -1)
- if (dcc->sess->external_port != 0)
- external_port = dcc->sess->external_port;
- external_port = dcc->local_port;
- if (dcc->sess->external_addr != 0)
- external_addr = dcc->sess->external_addr;
- external_addr = dcc->local_addr;
- addr.s_addr = external_addr;
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// dcc7_listen_and_send_info() "
- "sending IP address %s and port %d\n",
- inet_ntoa(addr), external_port);
- memset(&pkt, 0, sizeof(pkt));
- pkt.uin = gg_fix32(dcc->peer_uin);
- pkt.type = GG_DCC7_TYPE_P2P;
- snprintf((char*) pkt.info, sizeof(pkt.info), "%s %d", inet_ntoa(addr), external_port);
- snprintf((char*) pkt.hash, sizeof(pkt.hash), "%u", external_addr + external_port * rand());
- return gg_send_packet(dcc->sess, GG_DCC7_INFO, &pkt, sizeof(pkt), NULL);
- * \internal Odwraca połączenie po nieudanym connect()
- * \param dcc Struktura połączenia
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-static int gg_dcc7_reverse_connect(struct gg_dcc7 *dcc)
- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_reverse_connect(%p)\n", dcc);
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_reverse_connect() already reverse connection\n");
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_reverse_connect() timeout, trying reverse connection\n");
- return gg_dcc7_listen_and_send_info(dcc);
- * \internal Wysyła do serwera żądanie nadania identyfikatora sesji
- * \param sess Struktura sesji
- * \param type Rodzaj połączenia (\c GG_DCC7_TYPE_FILE lub \c GG_DCC7_TYPE_VOICE)
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-static int gg_dcc7_request_id(struct gg_session *sess, uint32_t type)
- struct gg_dcc7_id_request pkt;
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_request_id(%p, %d)\n", sess, type);
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_request_id() invalid parameters\n");
- if (sess->state != GG_STATE_CONNECTED) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_request_id() not connected\n");
- if (type != GG_DCC7_TYPE_VOICE && type != GG_DCC7_TYPE_FILE) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_request_id() invalid transfer type (%d)\n", type);
- memset(&pkt, 0, sizeof(pkt));
- pkt.type = gg_fix32(type);
- return gg_send_packet(sess, GG_DCC7_ID_REQUEST, &pkt, sizeof(pkt), NULL);
- * \internal Rozpoczyna wysyłanie pliku.
- * Funkcja jest wykorzystywana przez \c gg_dcc7_send_file() oraz
- * \c gg_dcc_send_file_fd().
- * \param sess Struktura sesji
- * \param rcpt Numer odbiorcy
- * \param fd Deskryptor pliku
- * \param size Rozmiar pliku
- * \param filename1250 Nazwa pliku w kodowaniu CP-1250
- * \param hash Skrót SHA-1 pliku
- * \param seek Flaga mówiąca, czy można używać lseek()
- * \return Struktura \c gg_dcc7 lub \c NULL w przypadku błędu
-static struct gg_dcc7 *gg_dcc7_send_file_common(struct gg_session *sess,
- uin_t rcpt, int fd, size_t size, const char *filename1250,
- const char *hash, int seek)
- struct gg_dcc7 *dcc = NULL;
- if (!sess || !rcpt || !filename1250 || !hash || fd == -1) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_send_file_common() invalid parameters\n");
- if (!(dcc = malloc(sizeof(struct gg_dcc7)))) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_send_file_common() not enough memory\n");
- if (gg_dcc7_request_id(sess, GG_DCC7_TYPE_FILE) == -1)
- memset(dcc, 0, sizeof(struct gg_dcc7));
- dcc->type = GG_SESSION_DCC7_SEND;
- dcc->dcc_type = GG_DCC7_TYPE_FILE;
- dcc->state = GG_STATE_REQUESTING_ID;
- dcc->timeout = GG_DEFAULT_TIMEOUT;
- strncpy((char*) dcc->filename, filename1250, GG_DCC7_FILENAME_LEN);
- dcc->filename[GG_DCC7_FILENAME_LEN] = 0;
- memcpy(dcc->hash, hash, GG_DCC7_HASH_LEN);
- if (gg_dcc7_session_add(sess, dcc) == -1)
- * Rozpoczyna wysyłanie pliku o danej nazwie.
- * \param sess Struktura sesji
- * \param rcpt Numer odbiorcy
- * \param filename Nazwa pliku w lokalnym systemie plików
- * \param filename1250 Nazwa pliku w kodowaniu CP-1250
- * \param hash Skrót SHA-1 pliku (lub \c NULL jeśli ma być wyznaczony)
- * \return Struktura \c gg_dcc7 lub \c NULL w przypadku błędu
-struct gg_dcc7 *gg_dcc7_send_file(struct gg_session *sess, uin_t rcpt,
- const char *filename, const char *filename1250, const char *hash)
- struct gg_dcc7 *dcc = NULL;
- char hash_buf[GG_DCC7_HASH_LEN];
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_send_file(%p, %d,"
- " \"%s\", %p)\n", sess, rcpt, filename, hash);
- if (!sess || !rcpt || !filename) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_send_file() invalid parameters\n");
- filename1250 = filename;
- if ((fd = open(filename, O_RDONLY)) == -1) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_send_file() open() failed (%s)\n", strerror(errno));
- if (fstat(fd, &st) == -1) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_send_file() "
- "fstat() failed (%s)\n", strerror(errno));
- if ((st.st_mode & S_IFDIR)) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_send_file() that's a directory\n");
- if (gg_file_hash_sha1(fd, (uint8_t*) hash_buf) == -1)
- if ((tmp = strrchr(filename1250, '/')))
- filename1250 = tmp + 1;
- if (!(dcc = gg_dcc7_send_file_common(sess, rcpt, fd, st.st_size, filename1250, hash, 1)))
- * \internal Rozpoczyna wysyłanie pliku o danym deskryptorze.
- * \note Wysyłanie pliku nie będzie działać poprawnie, jeśli deskryptor
- * źródłowy jest w trybie nieblokującym i w pewnym momencie zabraknie danych.
- * \param sess Struktura sesji
- * \param rcpt Numer odbiorcy
- * \param fd Deskryptor pliku
- * \param size Rozmiar pliku
- * \param filename1250 Nazwa pliku w kodowaniu CP-1250
- * \param hash Skrót SHA-1 pliku
- * \return Struktura \c gg_dcc7 lub \c NULL w przypadku błędu
-struct gg_dcc7 *gg_dcc7_send_file_fd(struct gg_session *sess, uin_t rcpt,
- int fd, size_t size, const char *filename1250, const char *hash)
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_send_file_fd(%p, "
- "%d, %d, %" GG_SIZE_FMT ", \"%s\", %p)\n",
- sess, rcpt, fd, size, filename1250, hash);
- return gg_dcc7_send_file_common(sess, rcpt, fd, size, filename1250, hash, 0);
- * Potwierdza chęć odebrania pliku.
- * \param dcc Struktura połączenia
- * \param offset Początkowy offset przy wznawianiu przesyłania pliku
- * \note Biblioteka nie zmienia położenia w odbieranych plikach. Jeśli offset
- * początkowy jest różny od zera, należy ustawić go funkcją \c lseek() lub
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_dcc7_accept(struct gg_dcc7 *dcc, unsigned int offset)
- struct gg_dcc7_accept pkt;
- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_accept(%p, %d)\n", dcc, offset);
- if (!dcc || !dcc->sess) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_accept() invalid parameters\n");
- memset(&pkt, 0, sizeof(pkt));
- pkt.uin = gg_fix32(dcc->peer_uin);
- pkt.offset = gg_fix32(offset);
- if (gg_send_packet(dcc->sess, GG_DCC7_ACCEPT, &pkt, sizeof(pkt), NULL) == -1)
- return gg_dcc7_listen_and_send_info(dcc);
- * Odrzuca próbę przesłania pliku.
- * \param dcc Struktura połączenia
- * \param reason Powód odrzucenia
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_dcc7_reject(struct gg_dcc7 *dcc, int reason)
- struct gg_dcc7_reject pkt;
- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_reject(%p, %d)\n", dcc, reason);
- if (!dcc || !dcc->sess) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_reject() invalid parameters\n");
- memset(&pkt, 0, sizeof(pkt));
- pkt.uin = gg_fix32(dcc->peer_uin);
- pkt.reason = gg_fix32(reason);
- return gg_send_packet(dcc->sess, GG_DCC7_REJECT, &pkt, sizeof(pkt), NULL);
- * \internal Obsługuje pakiet identyfikatora połączenia bezpośredniego.
- * \param sess Struktura sesji
- * \param e Struktura zdarzenia
- * \param payload Treść pakietu
- * \param len Długość pakietu
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_dcc7_handle_id(struct gg_session *sess, struct gg_event *e, const void *payload, int len)
- const struct gg_dcc7_id_reply *p = payload;
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_handle_id(%p, %p, %p, %d)\n", sess, e, payload, len);
- for (tmp = sess->dcc7_list; tmp; tmp = tmp->next) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// checking dcc %p, "
- "state %d, type %d\n", tmp, tmp->state, tmp->dcc_type);
- if (tmp->state != GG_STATE_REQUESTING_ID || tmp->dcc_type != (int) gg_fix32(p->type))
- switch (tmp->dcc_type) {
- case GG_DCC7_TYPE_FILE:
- memset(&s, 0, sizeof(s));
- s.type = gg_fix32(GG_DCC7_TYPE_FILE);
- s.uin_from = gg_fix32(tmp->uin);
- s.uin_to = gg_fix32(tmp->peer_uin);
- s.size = gg_fix32(tmp->size);
- /* Uwaga: To nie jest ciąg kończony zerem.
- * Note: This is not a null-terminated string. */
- sizeof(s.filename) == sizeof(tmp->filename) - 1,
- filename_sizes_does_not_match);
- memcpy((char*)s.filename, (char*)tmp->filename, sizeof(s.filename));
- tmp->state = GG_STATE_WAITING_FOR_ACCEPT;
- tmp->timeout = GG_DCC7_TIMEOUT_FILE_ACK;
- return gg_send_packet(sess, GG_DCC7_NEW, &s, sizeof(s), NULL);
- * \internal Obsługuje pakiet akceptacji połączenia bezpośredniego.
- * \param sess Struktura sesji
- * \param e Struktura zdarzenia
- * \param payload Treść pakietu
- * \param len Długość pakietu
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_dcc7_handle_accept(struct gg_session *sess, struct gg_event *e, const void *payload, int len)
- const struct gg_dcc7_accept *p = payload;
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_handle_accept(%p, %p, %p, %d)\n", sess, e, payload, len);
- if (!(dcc = gg_dcc7_session_find(sess, p->id, gg_fix32(p->uin)))) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_accept() unknown dcc session\n");
- /* XXX wysłać reject? */
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
- if (dcc->state != GG_STATE_WAITING_FOR_ACCEPT) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_accept() invalid state\n");
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
- /* XXX czy dla odwrotnego połączenia powinniśmy wywołać już zdarzenie GG_DCC7_ACCEPT? */
- dcc->offset = gg_fix32(p->offset);
- dcc->state = GG_STATE_WAITING_FOR_INFO;
- * \internal Obsługuje pakiet informacji o połączeniu bezpośrednim.
- * \param sess Struktura sesji
- * \param e Struktura zdarzenia
- * \param payload Treść pakietu
- * \param len Długość pakietu
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_dcc7_handle_info(struct gg_session *sess, struct gg_event *e, const void *payload, int len)
- const struct gg_dcc7_info *p = payload;
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_handle_info(%p, %p, %p, %d)\n", sess, e, payload, len);
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "// gg_dcc7_handle_info() "
- "received address: %s, hash: %s\n", p->info, p->hash);
- if (!(dcc = gg_dcc7_session_find(sess, p->id, gg_fix32(p->uin)))) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() unknown dcc session\n");
- if (dcc->state == GG_STATE_CONNECTED) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() state is already connected\n");
- if ((dcc->remote_addr = inet_addr(p->info)) == INADDR_NONE) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() invalid IP address\n");
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
- if (!(tmp = strchr(p->info, ' ')) || !(dcc->remote_port = atoi(tmp + 1))) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() invalid IP port\n");
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
- if (dcc->state == GG_STATE_WAITING_FOR_INFO) {
- gg_debug_session(sess, GG_DEBUG_MISC,
- "// gg_dcc7_handle_info() waiting for info "
- gg_dcc7_listen_and_send_info(dcc);
- e->type = GG_EVENT_DCC7_PENDING;
- e->event.dcc7_pending.dcc7 = dcc;
- case GG_DCC7_TYPE_SERVER:
- if (!(tmp = strstr(p->info, "GG"))) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() unknown info packet\n");
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
-#if defined(HAVE__STRTOUI64) || defined(HAVE_STRTOULL)
- cid = _strtoui64(tmp + 2, NULL, 0);
- cid = strtoull(tmp + 2, NULL, 0);
- gg_debug_session(sess, GG_DEBUG_MISC,
- "// gg_dcc7_handle_info() info.str=%s, "
- "info.id=%llu, sess.id=%llu\n", tmp + 2, cid,
- *((unsigned long long*) &dcc->cid));
- if (memcmp(&dcc->cid, &cid, sizeof(cid)) != 0) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() invalid session id\n");
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
- if (gg_dcc7_get_relay_addr(dcc) == -1) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_handle_info() unable to retrieve relay address\n");
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc7_error = GG_ERROR_DCC7_RELAY;
- /* XXX wysyłać dopiero jeśli uda się połączyć z serwerem? */
- gg_send_packet(dcc->sess, GG_DCC7_INFO, payload, len, NULL);
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info()"
- " unhandled transfer type (%d)\n", p->type);
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
- /* jeśli nadal czekamy na połączenie przychodzące, a druga strona nie
- * daje rady i oferuje namiary na siebie, bierzemy co dają.
- if (dcc->state != GG_STATE_WAITING_FOR_INFO && (dcc->state != GG_STATE_LISTENING || dcc->reverse)) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() invalid state\n");
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
- if (dcc->state == GG_STATE_LISTENING) {
- if (dcc->type == GG_SESSION_DCC7_SEND) {
- e->type = GG_EVENT_DCC7_ACCEPT;
- e->event.dcc7_accept.dcc7 = dcc;
- e->event.dcc7_accept.type = gg_fix32(p->type);
- e->event.dcc7_accept.remote_ip = dcc->remote_addr;
- e->event.dcc7_accept.remote_port = dcc->remote_port;
- e->type = GG_EVENT_DCC7_PENDING;
- e->event.dcc7_pending.dcc7 = dcc;
- if (gg_dcc7_connect(dcc) == -1) {
- if (gg_dcc7_reverse_connect(dcc) == -1) {
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc7_error = GG_ERROR_DCC7_NET;
- * \internal Obsługuje pakiet odrzucenia połączenia bezpośredniego.
- * \param sess Struktura sesji
- * \param e Struktura zdarzenia
- * \param payload Treść pakietu
- * \param len Długość pakietu
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_dcc7_handle_reject(struct gg_session *sess, struct gg_event *e, const void *payload, int len)
- const struct gg_dcc7_reject *p = payload;
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_handle_reject(%p, %p, %p, %d)\n", sess, e, payload, len);
- if (!(dcc = gg_dcc7_session_find(sess, p->id, gg_fix32(p->uin)))) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_reject() unknown dcc session\n");
- if (dcc->state != GG_STATE_WAITING_FOR_ACCEPT) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_reject() invalid state\n");
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
- e->type = GG_EVENT_DCC7_REJECT;
- e->event.dcc7_reject.dcc7 = dcc;
- e->event.dcc7_reject.reason = gg_fix32(p->reason);
- /* XXX ustawić state na rejected? */
- * \internal Obsługuje pakiet nowego połączenia bezpośredniego.
- * \param sess Struktura sesji
- * \param e Struktura zdarzenia
- * \param payload Treść pakietu
- * \param len Długość pakietu
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_dcc7_handle_new(struct gg_session *sess, struct gg_event *e, const void *payload, int len)
- const struct gg_dcc7_new *p = payload;
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_handle_new(%p, %p, %p, %d)\n", sess, e, payload, len);
- switch (gg_fix32(p->type)) {
- case GG_DCC7_TYPE_FILE:
- if (!(dcc = malloc(sizeof(struct gg_dcc7)))) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_new() not enough memory\n");
- memset(dcc, 0, sizeof(struct gg_dcc7));
- dcc->type = GG_SESSION_DCC7_GET;
- dcc->dcc_type = GG_DCC7_TYPE_FILE;
- dcc->peer_uin = gg_fix32(p->uin_from);
- if (gg_dcc7_session_add(sess, dcc) == -1) {
- gg_debug_session(sess, GG_DEBUG_MISC,
- "// gg_dcc7_handle_new() unable to "
- dcc->size = gg_fix32(p->size);
- strncpy((char*) dcc->filename, (char*) p->filename, GG_DCC7_FILENAME_LEN);
- dcc->filename[GG_DCC7_FILENAME_LEN] = 0;
- memcpy(dcc->hash, p->hash, GG_DCC7_HASH_LEN);
- e->type = GG_EVENT_DCC7_NEW;
- e->event.dcc7_new = dcc;
- case GG_DCC7_TYPE_VOICE:
- if (!(dcc = malloc(sizeof(struct gg_dcc7)))) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_packet() not enough memory\n");
- memset(dcc, 0, sizeof(struct gg_dcc7));
- dcc->type = GG_SESSION_DCC7_VOICE;
- dcc->dcc_type = GG_DCC7_TYPE_VOICE;
- dcc->peer_uin = gg_fix32(p->uin_from);
- if (gg_dcc7_session_add(sess, dcc) == -1) {
- gg_debug_session(sess, GG_DEBUG_MISC,
- "// gg_dcc7_handle_new() unable to add "
- e->type = GG_EVENT_DCC7_NEW;
- e->event.dcc7_new = dcc;
- gg_debug_session(sess, GG_DEBUG_MISC,
- "// gg_dcc7_handle_new() unknown dcc type (%d) "
- "from %u\n", gg_fix32(p->type),
- gg_fix32(p->uin_from));
- * \internal Ustawia odpowiednie stany wewnętrzne w zależności od rodzaju
- * \param dcc Struktura połączenia
- * \return 0 jeśli się powiodło, -1 w przypadku błędu.
-static int gg_dcc7_postauth_fixup(struct gg_dcc7 *dcc)
- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_postauth_fixup(%p)\n", dcc);
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_postauth_fixup() invalid parameters\n");
- case GG_SESSION_DCC7_GET:
- dcc->state = GG_STATE_GETTING_FILE;
- dcc->check = GG_CHECK_READ;
- case GG_SESSION_DCC7_SEND:
- dcc->state = GG_STATE_SENDING_FILE;
- dcc->check = GG_CHECK_WRITE;
- case GG_SESSION_DCC7_VOICE:
- dcc->state = GG_STATE_READING_VOICE_DATA;
- dcc->check = GG_CHECK_READ;
- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
- * Funkcja zwraca strukturę zdarzenia \c gg_event. Jeśli rodzaj zdarzenia
- * to \c GG_EVENT_NONE, nie wydarzyło się jeszcze nic wartego odnotowania.
- * Strukturę zdarzenia należy zwolnić funkcja \c gg_event_free().
- * \param dcc Struktura połączenia
- * \return Struktura zdarzenia lub \c NULL jeśli wystąpił błąd
-struct gg_event *gg_dcc7_watch_fd(struct gg_dcc7 *dcc)
- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_watch_fd(%p)\n", dcc);
- if (!dcc || (dcc->type != GG_SESSION_DCC7_SEND &&
- dcc->type != GG_SESSION_DCC7_GET &&
- dcc->type != GG_SESSION_DCC7_VOICE))
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() invalid parameters\n");
- if (!(e = malloc(sizeof(struct gg_event)))) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() not enough memory\n");
- memset(e, 0, sizeof(struct gg_event));
- e->type = GG_EVENT_NONE;
- case GG_STATE_LISTENING:
- struct sockaddr_in sin;
- socklen_t sin_len = sizeof(sin);
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_LISTENING\n");
- if ((fd = accept(dcc->fd, (struct sockaddr*) &sin, &sin_len)) == -1) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC,
- "// gg_dcc7_watch_fd() accept() failed "
- "(%s)\n", strerror(errno));
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd()"
- " connection from %s:%d\n",
- inet_ntoa(sin.sin_addr), htons(sin.sin_port));
- if (!gg_fd_set_nonblocking(fd)) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC,
- "// gg_dcc7_watch_fd() can't set "
- "nonblocking (%s)\n", strerror(errno));
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE;
- dcc->state = GG_STATE_READING_ID;
- dcc->check = GG_CHECK_READ;
- dcc->timeout = GG_DEFAULT_TIMEOUT;
- dcc->remote_port = ntohs(sin.sin_port);
- dcc->remote_addr = sin.sin_addr.s_addr;
- e->type = GG_EVENT_DCC7_CONNECTED;
- e->event.dcc7_connected.dcc7 = dcc;
- case GG_STATE_CONNECTING:
- int res = 0, error = 0;
- socklen_t error_size = sizeof(error);
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_CONNECTING\n");
- if (error || (res = getsockopt(dcc->fd, SOL_SOCKET,
- SO_ERROR, &error, &error_size)) == -1 ||
- gg_debug_dcc(dcc, GG_DEBUG_MISC,
- "// gg_dcc7_watch_fd() connection "
- "failed (%s)\n", (res == -1) ?
- strerror(errno) : strerror(error));
- for (dcc->relay_index++;
- dcc->relay_index < dcc->relay_count;
- dcc->remote_addr = dcc->relay_list[dcc->relay_index].addr;
- dcc->remote_port = dcc->relay_list[dcc->relay_index].port;
- if (gg_dcc7_connect(dcc) == 0)
- if (dcc->relay_index >= dcc->relay_count) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC,
- "// gg_dcc7_watch_fd() "
- "no relay available\n");
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc_error = GG_ERROR_DCC7_RELAY;
- if (gg_dcc7_reverse_connect(dcc) != -1) {
- e->type = GG_EVENT_DCC7_PENDING;
- e->event.dcc7_pending.dcc7 = dcc;
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc_error = GG_ERROR_DCC7_NET;
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() connected, sending id\n");
- dcc->state = GG_STATE_SENDING_ID;
- dcc->check = GG_CHECK_WRITE;
- dcc->timeout = GG_DEFAULT_TIMEOUT;
- case GG_STATE_READING_ID:
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_READING_ID\n");
- struct gg_dcc7_welcome_p2p welcome, welcome_ok;
- welcome_ok.id = dcc->cid;
- if ((res = recv(dcc->fd, &welcome, sizeof(welcome), 0)) != sizeof(welcome)) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC,
- "// gg_dcc7_watch_fd() recv() "
- "failed (%d, %s)\n", res,
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE;
- if (memcmp(&welcome, &welcome_ok, sizeof(welcome))) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() invalid id\n");
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE;
- struct gg_dcc7_welcome_server welcome, welcome_ok;
- welcome_ok.magic = GG_DCC7_WELCOME_SERVER;
- welcome_ok.id = dcc->cid;
- if ((res = recv(dcc->fd, &welcome, sizeof(welcome), 0)) != sizeof(welcome)) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC,
- "// gg_dcc7_watch_fd() recv() "
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE;
- if (memcmp(&welcome, &welcome_ok, sizeof(welcome)) != 0) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() invalid id\n");
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE;
- dcc->state = GG_STATE_SENDING_ID;
- dcc->check = GG_CHECK_WRITE;
- dcc->timeout = GG_DEFAULT_TIMEOUT;
- gg_dcc7_postauth_fixup(dcc);
- dcc->timeout = GG_DEFAULT_TIMEOUT;
- case GG_STATE_SENDING_ID:
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_SENDING_ID\n");
- struct gg_dcc7_welcome_p2p welcome;
- if ((res = send(dcc->fd, &welcome, sizeof(welcome), 0)) != sizeof(welcome)) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC,
- "// gg_dcc7_watch_fd() send() "
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE;
- struct gg_dcc7_welcome_server welcome;
- welcome.magic = gg_fix32(GG_DCC7_WELCOME_SERVER);
- if ((res = send(dcc->fd, &welcome, sizeof(welcome), 0)) != sizeof(welcome)) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC,
- "// gg_dcc7_watch_fd() send() "
- "failed (%d, %s)\n", res,
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE;
- gg_dcc7_postauth_fixup(dcc);
- dcc->timeout = GG_DEFAULT_TIMEOUT;
- dcc->state = GG_STATE_READING_ID;
- dcc->check = GG_CHECK_READ;
- dcc->timeout = GG_DEFAULT_TIMEOUT;
- case GG_STATE_SENDING_FILE:
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd()"
- " GG_STATE_SENDING_FILE (offset=%d, size=%d)\n",
- dcc->offset, dcc->size);
- if (dcc->offset >= dcc->size) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() offset >= size, finished\n");
- e->type = GG_EVENT_DCC7_DONE;
- e->event.dcc7_done.dcc7 = dcc;
- if (dcc->seek && lseek(dcc->file_fd, dcc->offset, SEEK_SET) == (off_t) -1) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC,
- "// gg_dcc7_watch_fd() lseek() failed "
- "(%s)\n", strerror(errno));
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc_error = GG_ERROR_DCC7_FILE;
- if ((chunk = dcc->size - dcc->offset) > sizeof(buf))
- if ((res = read(dcc->file_fd, buf, chunk)) < 1) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC,
- "// gg_dcc7_watch_fd() read() failed "
- "(res=%d, %s)\n", res, strerror(errno));
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc_error = (res == -1) ? GG_ERROR_DCC7_FILE : GG_ERROR_DCC7_EOF;
- if ((res = send(dcc->fd, buf, res, 0)) == -1) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC,
- "// gg_dcc7_watch_fd() send() failed "
- "(%s)\n", strerror(errno));
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc_error = GG_ERROR_DCC7_NET;
- if (dcc->offset >= dcc->size) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() finished\n");
- e->type = GG_EVENT_DCC7_DONE;
- e->event.dcc7_done.dcc7 = dcc;
- dcc->state = GG_STATE_SENDING_FILE;
- dcc->check = GG_CHECK_WRITE;
- dcc->timeout = GG_DCC7_TIMEOUT_SEND;
- case GG_STATE_GETTING_FILE:
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd()"
- " GG_STATE_GETTING_FILE (offset=%d, size=%d)\n",
- dcc->offset, dcc->size);
- if (dcc->offset >= dcc->size) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() finished\n");
- e->type = GG_EVENT_DCC7_DONE;
- e->event.dcc7_done.dcc7 = dcc;
- if ((res = recv(dcc->fd, buf, sizeof(buf), 0)) < 1) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC,
- "// gg_dcc7_watch_fd() recv() failed "
- "(fd=%d, res=%d, %s)\n", dcc->fd, res,
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc_error = (res == -1) ? GG_ERROR_DCC7_NET : GG_ERROR_DCC7_EOF;
- /* XXX zapisywać do skutku? */
- if ((wres = write(dcc->file_fd, buf, res)) < res) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC,
- "// gg_dcc7_watch_fd() write() failed "
- "(fd=%d, res=%d, %s)\n", dcc->file_fd,
- wres, strerror(errno));
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc_error = GG_ERROR_DCC7_FILE;
- if (dcc->offset >= dcc->size) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() finished\n");
- e->type = GG_EVENT_DCC7_DONE;
- e->event.dcc7_done.dcc7 = dcc;
- dcc->state = GG_STATE_GETTING_FILE;
- dcc->check = GG_CHECK_READ;
- dcc->timeout = GG_DCC7_TIMEOUT_GET;
- case GG_STATE_RESOLVING_RELAY:
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_RESOLVING_RELAY\n");
- res = gg_resolver_recv(dcc->fd, &addr, sizeof(addr));
- } while (res == -1 && errno == EINTR);
- dcc->sess->resolver_cleanup(&dcc->resolver, 0);
- if (res != sizeof(addr) || addr.s_addr == INADDR_NONE) {
- int errno_save = errno;
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() resolving failed\n");
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc_error = GG_ERROR_DCC7_RELAY;
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd()"
- " resolved, connecting to %s:%d\n",
- inet_ntoa(addr), GG_RELAY_PORT);
- if ((dcc->fd = gg_connect(&addr, GG_RELAY_PORT, 1)) == -1) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC,
- "// gg_dcc7_watch_fd() connection "
- "failed (errno=%d, %s), critical\n",
- errno, strerror(errno));
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc_error = GG_ERROR_DCC7_RELAY;
- dcc->state = GG_STATE_CONNECTING_RELAY;
- dcc->check = GG_CHECK_WRITE;
- dcc->timeout = GG_DEFAULT_TIMEOUT;
- e->type = GG_EVENT_DCC7_PENDING;
- e->event.dcc7_pending.dcc7 = dcc;
- case GG_STATE_CONNECTING_RELAY:
- socklen_t res_size = sizeof(res);
- struct gg_dcc7_relay_req pkt;
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_CONNECTING_RELAY\n");
- if (getsockopt(dcc->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) != 0 || res != 0) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC,
- "// gg_dcc7_watch_fd() connection "
- "failed (errno=%d, %s)\n",
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc_error = GG_ERROR_DCC7_RELAY;
- memset(&pkt, 0, sizeof(pkt));
- pkt.magic = gg_fix32(GG_DCC7_RELAY_REQUEST);
- pkt.len = gg_fix32(sizeof(pkt));
- pkt.type = gg_fix16(GG_DCC7_RELAY_TYPE_SERVER);
- pkt.dunno1 = gg_fix16(GG_DCC7_RELAY_DUNNO1);
- gg_debug_dcc(dcc, GG_DEBUG_DUMP, "// gg_dcc7_watch_fd()"
- " send pkt(0x%.2x)\n", gg_fix32(pkt.magic));
- gg_debug_dump_dcc(dcc, GG_DEBUG_DUMP, (const char*) &pkt, sizeof(pkt));
- if ((res = send(dcc->fd, &pkt, sizeof(pkt), 0)) != sizeof(pkt)) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() sending failed\n");
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc_error = GG_ERROR_DCC7_RELAY;
- dcc->state = GG_STATE_READING_RELAY;
- dcc->check = GG_CHECK_READ;
- dcc->timeout = GG_DEFAULT_TIMEOUT;
- case GG_STATE_READING_RELAY:
- struct gg_dcc7_relay_reply *pkt;
- struct gg_dcc7_relay_reply_server srv;
- size_t max_relay_count = (sizeof(buf) - sizeof(*pkt)) / sizeof(srv);
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_READING_RELAY\n");
- if ((res = recv(dcc->fd, buf, sizeof(buf), 0)) < (int) sizeof(*pkt)) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC,
- "// gg_dcc7_watch_fd() recv() failed "
- "(%d, %s)\n", res, strerror(errno));
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc_error = GG_ERROR_DCC7_RELAY;
- pkt = (struct gg_dcc7_relay_reply*) buf;
- if (gg_fix32(pkt->magic) != GG_DCC7_RELAY_REPLY ||
- gg_fix32(pkt->rcount) < 1 ||
- gg_fix32(pkt->rcount) > 256 ||
- gg_fix32(pkt->len) < sizeof(*pkt) +
- gg_fix32(pkt->rcount) * sizeof(srv))
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_wathc_fd() invalid reply\n");
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc_error = GG_ERROR_DCC7_RELAY;
- gg_debug_dcc(dcc, GG_DEBUG_DUMP,
- "// gg_dcc7_get_relay() read pkt(0x%.2x)\n",
- gg_debug_dump_dcc(dcc, GG_DEBUG_DUMP, buf, res);
- dcc->relay_count = gg_fix32(pkt->rcount);
- if (dcc->relay_count > 0xffff ||
- (size_t)dcc->relay_count > max_relay_count)
- gg_debug_dcc(dcc, GG_DEBUG_MISC,
- "// gg_dcc7_watch_fd() relay_count out "
- "of bounds (%d)\n", dcc->relay_count);
- dcc->relay_list = malloc(dcc->relay_count * sizeof(gg_dcc7_relay_t));
- if (dcc->relay_list == NULL) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() not enough memory\n");
- for (i = 0; i < dcc->relay_count; i++) {
- memcpy(&srv, buf + sizeof(*pkt) + i * sizeof(srv), sizeof(srv));
- dcc->relay_list[i].addr = srv.addr;
- dcc->relay_list[i].port = gg_fix16(srv.port);
- dcc->relay_list[i].family = srv.family;
- addr.s_addr = srv.addr;
- gg_debug_dcc(dcc, GG_DEBUG_MISC,
- "// %s %d %d\n", inet_ntoa(addr),
- gg_fix16(srv.port), srv.family);
- for (; dcc->relay_index < dcc->relay_count; dcc->relay_index++) {
- dcc->remote_addr = dcc->relay_list[dcc->relay_index].addr;
- dcc->remote_port = dcc->relay_list[dcc->relay_index].port;
- if (gg_dcc7_connect(dcc) == 0)
- if (dcc->relay_index >= dcc->relay_count) {
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() no relay available\n");
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc_error = GG_ERROR_DCC7_RELAY;
- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_???\n");
- e->type = GG_EVENT_DCC7_ERROR;
- e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE;
- * Zwalnia zasoby używane przez połączenie bezpośrednie.
- * \param dcc Struktura połączenia
-void gg_dcc7_free(struct gg_dcc7 *dcc)
- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_free(%p)\n", dcc);
- if (dcc->file_fd != -1)
- gg_file_close(dcc->file_fd);
- gg_dcc7_session_remove(dcc->sess, dcc);
--- a/libpurple/protocols/gg/lib/debug.c Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,397 +0,0 @@
- * (C) Copyright 2001-2006 Wojtek Kaniewski <wojtekka@irc.pl>
- * Robert J. Woźny <speedy@ziew.org>
- * Arkadiusz Miśkiewicz <arekm@pld-linux.org>
- * Tomasz Chiliński <chilek@chilan.com>
- * Adam Wysocki <gophi@ekg.chmurka.net>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
- * \brief Funkcje odpluskwiania
- * Poziom rejestracji informacji odpluskwiających. Zmienna jest maską bitową
- * składającą się ze stałych \c GG_DEBUG_...
- * Funkcja, do której są przekazywane informacje odpluskwiające. Jeśli zarówno
- * ten \c gg_debug_handler, jak i \c gg_debug_handler_session, są równe
- * \c NULL, informacje są wysyłane do standardowego wyjścia błędu (\c stderr).
- * \param level Poziom rejestracji
- * \param format Format wiadomości (zgodny z \c printf)
- * \param ap Lista argumentów (zgodna z \c printf)
- * \note Funkcja jest przesłaniana przez \c gg_debug_handler_session.
-void (*gg_debug_handler)(int level, const char *format, va_list ap) = NULL;
- * Funkcja, do której są przekazywane informacje odpluskwiające. Jeśli zarówno
- * ten \c gg_debug_handler, jak i \c gg_debug_handler_session, są równe
- * \c NULL, informacje są wysyłane do standardowego wyjścia błędu.
- * \param sess Sesja której dotyczy informacja lub \c NULL
- * \param level Poziom rejestracji
- * \param format Format wiadomości (zgodny z \c printf)
- * \param ap Lista argumentów (zgodna z \c printf)
- * \note Funkcja przesłania przez \c gg_debug_handler_session.
-void (*gg_debug_handler_session)(struct gg_session *sess, int level, const char *format, va_list ap) = NULL;
- * Plik, do którego będą przekazywane informacje odpluskwiania.
- * Funkcja \c gg_debug() i pochodne mogą być przechwytywane przez aplikację
- * korzystającą z biblioteki, by wyświetlić je na żądanie użytkownika lub
- * zapisać do późniejszej analizy. Jeśli nie określono pliku, wybrane
- * informacje będą wysyłane do standardowego wyjścia błędu (\c stderr).
-FILE *gg_debug_file = NULL;
-#ifndef GG_DEBUG_DISABLE
- * \internal Przekazuje informacje odpluskwiania do odpowiedniej funkcji.
- * Jeśli aplikacja ustawiła odpowiednią funkcję obsługi w
- * \c gg_debug_handler_session lub \c gg_debug_handler, jest ona wywoływana.
- * W przeciwnym wypadku wynik jest wysyłany do standardowego wyjścia błędu.
- * \param sess Struktura sesji (może być \c NULL)
- * \param level Poziom informacji
- * \param format Format wiadomości (zgodny z \c printf)
- * \param ap Lista argumentów (zgodna z \c printf)
-void gg_debug_common(struct gg_session *sess, int level, const char *format, va_list ap)
- if (gg_debug_handler_session != NULL)
- (*gg_debug_handler_session)(sess, level, format, ap);
- else if (gg_debug_handler != NULL)
- (*gg_debug_handler)(level, format, ap);
- else if ((gg_debug_level & level) != 0)
- vfprintf((gg_debug_file) ? gg_debug_file : stderr, format, ap);
- * \internal Przekazuje informację odpluskawiania.
- * \param level Poziom wiadomości
- * \param format Format wiadomości (zgodny z \c printf)
-void gg_debug(int level, const char *format, ...)
- gg_debug_common(NULL, level, format, ap);
- * \internal Przekazuje informację odpluskwiania związaną z sesją.
- * \param gs Struktura sesji
- * \param level Poziom wiadomości
- * \param format Format wiadomości (zgodny z \c printf)
-void gg_debug_session(struct gg_session *gs, int level, const char *format, ...)
- gg_debug_common(gs, level, format, ap);
- * \internal Przekazuje zrzut bufora do odpluskwiania.
- * \param gs Struktura sesji
- * \param level Poziom wiadomości
- * \param buf Bufor danych
- * \param len Długość bufora danych
-void gg_debug_dump(struct gg_session *gs, int level, const char *buf, size_t len)
- for (i = 0; i < len; i += 16) {
- sprintf(line, "%.4x: ", i);
- for (j = 0; j < 16; j++) {
- sprintf(line + ofs, " %02x", (unsigned char) buf[i + j]);
- sprintf(line + ofs, " ");
- sprintf(line + ofs, " ");
- for (j = 0; j < 16; j++) {
- if (ch < 32 || ch > 126)
- gg_debug_session(gs, level, "%s", line);
- * \internal Zwraca ciąg z nazwą podanego stanu sesji.
- * \param state Stan sesji.
- * \return Ciąg z nazwą stanu
-const char *gg_debug_state(enum gg_state_t state)
-#define GG_DEBUG_STATE(x) case x: return #x;
- GG_DEBUG_STATE(GG_STATE_IDLE)
- GG_DEBUG_STATE(GG_STATE_RESOLVING)
- GG_DEBUG_STATE(GG_STATE_CONNECTING)
- GG_DEBUG_STATE(GG_STATE_READING_DATA)
- GG_DEBUG_STATE(GG_STATE_ERROR)
- GG_DEBUG_STATE(GG_STATE_CONNECTING_HUB)
- GG_DEBUG_STATE(GG_STATE_CONNECTING_GG)
- GG_DEBUG_STATE(GG_STATE_READING_KEY)
- GG_DEBUG_STATE(GG_STATE_READING_REPLY)
- GG_DEBUG_STATE(GG_STATE_CONNECTED)
- GG_DEBUG_STATE(GG_STATE_SENDING_QUERY)
- GG_DEBUG_STATE(GG_STATE_READING_HEADER)
- GG_DEBUG_STATE(GG_STATE_PARSING)
- GG_DEBUG_STATE(GG_STATE_DONE)
- GG_DEBUG_STATE(GG_STATE_LISTENING)
- GG_DEBUG_STATE(GG_STATE_READING_UIN_1)
- GG_DEBUG_STATE(GG_STATE_READING_UIN_2)
- GG_DEBUG_STATE(GG_STATE_SENDING_ACK)
- GG_DEBUG_STATE(GG_STATE_READING_ACK)
- GG_DEBUG_STATE(GG_STATE_READING_REQUEST)
- GG_DEBUG_STATE(GG_STATE_SENDING_REQUEST)
- GG_DEBUG_STATE(GG_STATE_SENDING_FILE_INFO)
- GG_DEBUG_STATE(GG_STATE_READING_PRE_FILE_INFO)
- GG_DEBUG_STATE(GG_STATE_READING_FILE_INFO)
- GG_DEBUG_STATE(GG_STATE_SENDING_FILE_ACK)
- GG_DEBUG_STATE(GG_STATE_READING_FILE_ACK)
- GG_DEBUG_STATE(GG_STATE_SENDING_FILE_HEADER)
- GG_DEBUG_STATE(GG_STATE_READING_FILE_HEADER)
- GG_DEBUG_STATE(GG_STATE_GETTING_FILE)
- GG_DEBUG_STATE(GG_STATE_SENDING_FILE)
- GG_DEBUG_STATE(GG_STATE_READING_VOICE_ACK)
- GG_DEBUG_STATE(GG_STATE_READING_VOICE_HEADER)
- GG_DEBUG_STATE(GG_STATE_READING_VOICE_SIZE)
- GG_DEBUG_STATE(GG_STATE_READING_VOICE_DATA)
- GG_DEBUG_STATE(GG_STATE_SENDING_VOICE_ACK)
- GG_DEBUG_STATE(GG_STATE_SENDING_VOICE_REQUEST)
- GG_DEBUG_STATE(GG_STATE_READING_TYPE)
- GG_DEBUG_STATE(GG_STATE_TLS_NEGOTIATION)
- GG_DEBUG_STATE(GG_STATE_REQUESTING_ID)
- GG_DEBUG_STATE(GG_STATE_WAITING_FOR_ACCEPT)
- GG_DEBUG_STATE(GG_STATE_WAITING_FOR_INFO)
- GG_DEBUG_STATE(GG_STATE_READING_ID)
- GG_DEBUG_STATE(GG_STATE_SENDING_ID)
- GG_DEBUG_STATE(GG_STATE_RESOLVING_GG)
- GG_DEBUG_STATE(GG_STATE_RESOLVING_RELAY)
- GG_DEBUG_STATE(GG_STATE_CONNECTING_RELAY)
- GG_DEBUG_STATE(GG_STATE_READING_RELAY)
- GG_DEBUG_STATE(GG_STATE_DISCONNECTING)
- GG_DEBUG_STATE(GG_STATE_CONNECT_HUB)
- GG_DEBUG_STATE(GG_STATE_CONNECT_PROXY_HUB)
- GG_DEBUG_STATE(GG_STATE_CONNECT_GG)
- GG_DEBUG_STATE(GG_STATE_CONNECT_PROXY_GG)
- GG_DEBUG_STATE(GG_STATE_CONNECTING_PROXY_HUB)
- GG_DEBUG_STATE(GG_STATE_CONNECTING_PROXY_GG)
- GG_DEBUG_STATE(GG_STATE_RESOLVE_HUB_SYNC)
- GG_DEBUG_STATE(GG_STATE_RESOLVE_HUB_ASYNC)
- GG_DEBUG_STATE(GG_STATE_RESOLVE_PROXY_HUB_SYNC)
- GG_DEBUG_STATE(GG_STATE_RESOLVE_PROXY_HUB_ASYNC)
- GG_DEBUG_STATE(GG_STATE_RESOLVE_PROXY_GG_SYNC)
- GG_DEBUG_STATE(GG_STATE_RESOLVE_PROXY_GG_ASYNC)
- GG_DEBUG_STATE(GG_STATE_RESOLVE_GG_SYNC)
- GG_DEBUG_STATE(GG_STATE_RESOLVE_GG_ASYNC)
- GG_DEBUG_STATE(GG_STATE_RESOLVING_HUB)
- GG_DEBUG_STATE(GG_STATE_RESOLVING_PROXY_HUB)
- GG_DEBUG_STATE(GG_STATE_RESOLVING_PROXY_GG)
- GG_DEBUG_STATE(GG_STATE_SEND_HUB)
- GG_DEBUG_STATE(GG_STATE_SEND_PROXY_HUB)
- GG_DEBUG_STATE(GG_STATE_SEND_PROXY_GG)
- GG_DEBUG_STATE(GG_STATE_SENDING_HUB)
- GG_DEBUG_STATE(GG_STATE_SENDING_PROXY_HUB)
- GG_DEBUG_STATE(GG_STATE_SENDING_PROXY_GG)
- GG_DEBUG_STATE(GG_STATE_READING_HUB)
- GG_DEBUG_STATE(GG_STATE_READING_PROXY_HUB)
- GG_DEBUG_STATE(GG_STATE_READING_PROXY_GG)
- /* Celowo nie ma default, żeby kompilator wyłapał brakujące stany */
- * \internal Zwraca ciąg z nazwą podanego zdarzenia.
- * \param event Zdarzenie.
- * \return Ciąg z nazwą zdarzenia
-const char *gg_debug_event(enum gg_event_t event)
-#define GG_DEBUG_EVENT(x) case x: return #x;
- GG_DEBUG_EVENT(GG_EVENT_NONE)
- GG_DEBUG_EVENT(GG_EVENT_MSG)
- GG_DEBUG_EVENT(GG_EVENT_NOTIFY)
- GG_DEBUG_EVENT(GG_EVENT_NOTIFY_DESCR)
- GG_DEBUG_EVENT(GG_EVENT_STATUS)
- GG_DEBUG_EVENT(GG_EVENT_ACK)
- GG_DEBUG_EVENT(GG_EVENT_PONG)
- GG_DEBUG_EVENT(GG_EVENT_CONN_FAILED)
- GG_DEBUG_EVENT(GG_EVENT_CONN_SUCCESS)
- GG_DEBUG_EVENT(GG_EVENT_DISCONNECT)
- GG_DEBUG_EVENT(GG_EVENT_DCC_NEW)
- GG_DEBUG_EVENT(GG_EVENT_DCC_ERROR)
- GG_DEBUG_EVENT(GG_EVENT_DCC_DONE)
- GG_DEBUG_EVENT(GG_EVENT_DCC_CLIENT_ACCEPT)
- GG_DEBUG_EVENT(GG_EVENT_DCC_CALLBACK)
- GG_DEBUG_EVENT(GG_EVENT_DCC_NEED_FILE_INFO)
- GG_DEBUG_EVENT(GG_EVENT_DCC_NEED_FILE_ACK)
- GG_DEBUG_EVENT(GG_EVENT_DCC_NEED_VOICE_ACK)
- GG_DEBUG_EVENT(GG_EVENT_DCC_VOICE_DATA)
- GG_DEBUG_EVENT(GG_EVENT_PUBDIR50_SEARCH_REPLY)
- GG_DEBUG_EVENT(GG_EVENT_PUBDIR50_READ)
- GG_DEBUG_EVENT(GG_EVENT_PUBDIR50_WRITE)
- GG_DEBUG_EVENT(GG_EVENT_STATUS60)
- GG_DEBUG_EVENT(GG_EVENT_NOTIFY60)
- GG_DEBUG_EVENT(GG_EVENT_USERLIST)
- GG_DEBUG_EVENT(GG_EVENT_IMAGE_REQUEST)
- GG_DEBUG_EVENT(GG_EVENT_IMAGE_REPLY)
- GG_DEBUG_EVENT(GG_EVENT_DCC_ACK)
- GG_DEBUG_EVENT(GG_EVENT_DCC7_NEW)
- GG_DEBUG_EVENT(GG_EVENT_DCC7_ACCEPT)
- GG_DEBUG_EVENT(GG_EVENT_DCC7_REJECT)
- GG_DEBUG_EVENT(GG_EVENT_DCC7_CONNECTED)
- GG_DEBUG_EVENT(GG_EVENT_DCC7_ERROR)
- GG_DEBUG_EVENT(GG_EVENT_DCC7_DONE)
- GG_DEBUG_EVENT(GG_EVENT_DCC7_PENDING)
- GG_DEBUG_EVENT(GG_EVENT_XML_EVENT)
- GG_DEBUG_EVENT(GG_EVENT_JSON_EVENT)
- GG_DEBUG_EVENT(GG_EVENT_ACK110)
- GG_DEBUG_EVENT(GG_EVENT_DISCONNECT_ACK)
- GG_DEBUG_EVENT(GG_EVENT_TYPING_NOTIFICATION)
- GG_DEBUG_EVENT(GG_EVENT_USER_DATA)
- GG_DEBUG_EVENT(GG_EVENT_MULTILOGON_MSG)
- GG_DEBUG_EVENT(GG_EVENT_MULTILOGON_INFO)
- GG_DEBUG_EVENT(GG_EVENT_USERLIST100_VERSION)
- GG_DEBUG_EVENT(GG_EVENT_USERLIST100_REPLY)
- GG_DEBUG_EVENT(GG_EVENT_IMTOKEN)
- GG_DEBUG_EVENT(GG_EVENT_PONG110)
- GG_DEBUG_EVENT(GG_EVENT_CHAT_INFO)
- GG_DEBUG_EVENT(GG_EVENT_CHAT_INFO_GOT_ALL)
- GG_DEBUG_EVENT(GG_EVENT_CHAT_INFO_UPDATE)
- GG_DEBUG_EVENT(GG_EVENT_CHAT_CREATED)
- GG_DEBUG_EVENT(GG_EVENT_CHAT_INVITE_ACK)
- /* Celowo nie ma default, żeby kompilator wyłapał brakujące zdarzenia */
-void gg_debug_common(struct gg_session *sess, int level, const char *format, va_list ap)
-void gg_debug(int level, const char *format, ...)
-void gg_debug_session(struct gg_session *gs, int level, const char *format, ...)
-void gg_debug_dump(struct gg_session *gs, int level, const char *buf, size_t len)
--- a/libpurple/protocols/gg/lib/debug.h Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
- * (C) Copyright 2009 Wojtek Kaniewski <wojtekka@irc.pl>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-void gg_debug_dump(struct gg_session *sess, int level, const char *buf, size_t len);
-void gg_debug_common(struct gg_session *sess, int level, const char *format, va_list ap);
-#endif /* LIBGADU_DEBUG_H */
--- a/libpurple/protocols/gg/lib/deflate.c Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,231 +0,0 @@
- * (C) Copyright 2011 Bartosz Brachaczek <b.brachaczek@gmail.com>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
- * \brief Funkcje kompresji Deflate
-#ifdef GG_CONFIG_HAVE_ZLIB
- * \internal Kompresuje dane wejściowe algorytmem Deflate z najwyższym
- * stopniem kompresji, tak samo jak oryginalny klient.
- * Wynik funkcji należy zwolnić za pomocą \c free.
- * \param in Ciąg znaków do skompresowania, zakończony \c \\0
- * \param out_lenp Wskaźnik na zmienną, do której zostanie zapisana
- * długość bufora wynikowego
- * \return Skompresowany ciąg znaków lub \c NULL w przypadku niepowodzenia.
-unsigned char *gg_deflate(const char *in, size_t *out_lenp)
-#ifdef GG_CONFIG_HAVE_ZLIB
- unsigned char *out, *out2;
- if (in == NULL || out_lenp == NULL)
- strm.avail_in = strlen(in);
- strm.next_in = (unsigned char*) in;
- ret = deflateInit(&strm, Z_BEST_COMPRESSION);
- gg_debug(GG_DEBUG_MISC, "// gg_deflate() deflateInit() failed (%d)\n", ret);
- out_len = deflateBound(&strm, strm.avail_in);
- gg_debug(GG_DEBUG_MISC, "// gg_deflate() not enough memory for "
- "output data (%" GG_SIZE_FMT ")\n", out_len);
- strm.avail_out = out_len;
- ret = deflate(&strm, Z_FINISH);
- if (ret == Z_STREAM_END)
- /* raczej nie powinno się zdarzyć przy Z_FINISH i out_len == deflateBound(),
- * ale dokumentacja zlib nie wyklucza takiej możliwości */
- out2 = realloc(out, out_len);
- gg_debug(GG_DEBUG_MISC, "// gg_deflate() not "
- "enough memory for output data (%"
- GG_SIZE_FMT ")\n", out_len);
- strm.avail_out = out_len / 2;
- strm.next_out = out + out_len / 2;
- gg_debug(GG_DEBUG_MISC, "// gg_deflate() deflate() "
- "failed (ret=%d, msg=%s)\n", ret,
- strm.msg != NULL ? strm.msg :
- "no error message provided");
- out_len = strm.total_out;
- out2 = realloc(out, out_len);
- gg_debug(GG_DEBUG_MISC, "// gg_deflate() not enough memory for "
- "output data (%" GG_SIZE_FMT ")\n", out_len);
- * \internal Dekompresuje dane wejściowe w formacie Deflate.
- * Wynik funkcji należy zwolnić za pomocą \c free.
- * \param in Bufor danych skompresowanych algorytmem Deflate
- * \param length Długość bufora wejściowego
- * \note Dokleja \c \\0 na końcu bufora wynikowego.
- * \return Zdekompresowany ciąg znaków, zakończony \c \\0,
- * lub \c NULL w przypadku niepowodzenia.
-char *gg_inflate(const unsigned char *in, size_t length)
-#ifdef GG_CONFIG_HAVE_ZLIB
- char *out = NULL, *out2;
- strm.avail_in = length;
- strm.next_in = (unsigned char*) in;
- ret = inflateInit(&strm);
- gg_debug(GG_DEBUG_MISC, "// gg_inflate() inflateInit() failed (%d)\n", ret);
- out2 = realloc(out, out_len);
- gg_debug(GG_DEBUG_MISC, "// gg_inflate() not enough "
- "memory for output data (%" GG_SIZE_FMT ")\n", out_len);
- strm.avail_out = out_len;
- strm.next_out = (unsigned char*) out;
- strm.avail_out = out_len / 2;
- strm.next_out = (unsigned char*) out + out_len / 2;
- ret = inflate(&strm, Z_NO_FLUSH);
- if (ret != Z_OK && ret != Z_STREAM_END) {
- gg_debug(GG_DEBUG_MISC, "// gg_inflate() inflate() "
- "failed (ret=%d, msg=%s)\n", ret,
- strm.msg != NULL ? strm.msg :
- "no error message provided");
- } while (ret != Z_STREAM_END);
- /* rezerwujemy ostatni znak na NULL-a */
- out_len = strm.total_out + 1;
- out2 = realloc(out, out_len);
- gg_debug(GG_DEBUG_MISC, "// gg_inflate() not enough memory for "
- "output data (%" GG_SIZE_FMT ")\n", out_len);
- out[out_len - 1] = '\0';
--- a/libpurple/protocols/gg/lib/deflate.h Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
- * (C) Copyright 2011 Bartosz Brachaczek <b.brachaczek@gmail.com>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-#ifndef LIBGADU_DEFLATE_H
-#define LIBGADU_DEFLATE_H
-unsigned char *gg_deflate(const char *in, size_t *out_lenp);
-char *gg_inflate(const unsigned char *in, size_t length);
-#endif /* LIBGADU_DEFLATE_H */
--- a/libpurple/protocols/gg/lib/encoding.c Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,272 +0,0 @@
- * (C) Copyright 2008-2009 Jakub Zawadzki <darkjames@darkjames.ath.cx>
- * Wojtek Kaniewski <wojtekka@irc.pl>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
- * \brief Funkcje konwersji kodowania tekstu
- * \internal Tablica konwersji CP1250 na Unikod.
-static const uint16_t table_cp1250[] =
- 0x20ac, '?', 0x201a, '?', 0x201e, 0x2026, 0x2020, 0x2021,
- '?', 0x2030, 0x0160, 0x2039, 0x015a, 0x0164, 0x017d, 0x0179,
- '?', 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
- '?', 0x2122, 0x0161, 0x203a, 0x015b, 0x0165, 0x017e, 0x017a,
- 0x00a0, 0x02c7, 0x02d8, 0x0141, 0x00a4, 0x0104, 0x00a6, 0x00a7,
- 0x00a8, 0x00a9, 0x015e, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x017b,
- 0x00b0, 0x00b1, 0x02db, 0x0142, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
- 0x00b8, 0x0105, 0x015f, 0x00bb, 0x013d, 0x02dd, 0x013e, 0x017c,
- 0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7,
- 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e,
- 0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7,
- 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df,
- 0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7,
- 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f,
- 0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7,
- 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9,
- * \internal Zamienia tekst kodowany CP1250 na UTF-8.
- * \param src Tekst źródłowy w CP1250.
- * \param src_length Długość ciągu źródłowego (nigdy ujemna).
- * \param dst_length Długość ciągu docelowego (jeśli -1, nieograniczona).
- * \return Zaalokowany bufor z tekstem w UTF-8.
-static char *gg_encoding_convert_cp1250_utf8(const char *src, int src_length, int dst_length)
- for (i = 0, len = 0; (src[i] != 0) && (i < src_length); i++) {
- if ((unsigned char) src[i] < 0x80)
- uc = (unsigned char) src[i];
- uc = table_cp1250[(unsigned char) src[i] - 128];
- if ((dst_length != -1) && (len > dst_length))
- result = malloc(len + 1);
- for (i = 0, j = 0; (src[i] != 0) && (i < src_length) && (j < len); i++) {
- if ((unsigned char) src[i] < 0x80)
- uc = (unsigned char) src[i];
- uc = table_cp1250[(unsigned char) src[i] - 128];
- result[j++] = (char) uc;
- result[j++] = 0xc0 | ((uc >> 6) & 0x1f);
- result[j++] = 0x80 | (uc & 0x3f);
- result[j++] = 0xe0 | ((uc >> 12) & 0x1f);
- result[j++] = 0x80 | ((uc >> 6) & 0x3f);
- result[j++] = 0x80 | (uc & 0x3f);
- * \internal Zamienia tekst kodowany UTF-8 na CP1250.
- * \param src Tekst źródłowy w UTF-8.
- * \param src_length Długość ciągu źródłowego (nigdy ujemna).
- * \param dst_length Długość ciągu docelowego (jeśli -1, nieograniczona).
- * \return Zaalokowany bufor z tekstem w CP1250.
-static char *gg_encoding_convert_utf8_cp1250(const char *src, int src_length, int dst_length)
- int i, j, len, uc_left = 0;
- uint32_t uc = 0, uc_min = 0;
- for (i = 0, len = 0; (src[i] != 0) && (i < src_length); i++) {
- if ((src[i] & 0xc0) != 0x80)
- if ((dst_length != -1) && (len > dst_length))
- result = malloc(len + 1);
- for (i = 0, j = 0; (src[i] != 0) && (i < src_length) && (j < len); i++) {
- if ((unsigned char) src[i] >= 0xf5) {
- /* Restricted sequences */
- } else if ((src[i] & 0xf8) == 0xf0) {
- } else if ((src[i] & 0xf0) == 0xe0) {
- } else if ((src[i] & 0xe0) == 0xc0) {
- } else if ((src[i] & 0xc0) == 0x80) {
- for (k = 0; k < 128; k++) {
- if (uc == table_cp1250[k]) {
- if (!valid && uc != 0xfeff) /* Byte Order Mark */
- if ((uc_left != 0) && (src[i] == 0))
- * \internal Zamienia kodowanie tekstu.
- * \param src Tekst źródłowy.
- * \param src_encoding Kodowanie tekstu źródłowego.
- * \param dst_encoding Kodowanie tekstu docelowego.
- * \param src_length Długość ciągu źródłowego w bajtach (jeśli -1, zostanie obliczona na podstawie zawartości \p src).
- * \param dst_length Długość ciągu docelowego w bajtach (jeśli -1, nieograniczona).
- * \return Zaalokowany bufor z tekstem w kodowaniu docelowym.
-char *gg_encoding_convert(const char *src, gg_encoding_t src_encoding,
- gg_encoding_t dst_encoding, int src_length, int dst_length)
- /* specjalny przypadek obsługiwany ekspresowo */
- if ((dst_encoding == src_encoding) && (dst_length == -1) && (src_length == -1))
- src_length = strlen(src);
- if (dst_encoding == src_encoding) {
- len = (src_length < dst_length) ? src_length : dst_length;
- result = malloc(len + 1);
- strncpy(result, src, len);
- if (dst_encoding == GG_ENCODING_CP1250 && src_encoding == GG_ENCODING_UTF8)
- return gg_encoding_convert_utf8_cp1250(src, src_length, dst_length);
- if (dst_encoding == GG_ENCODING_UTF8 && src_encoding == GG_ENCODING_CP1250)
- return gg_encoding_convert_cp1250_utf8(src, src_length, dst_length);
--- a/libpurple/protocols/gg/lib/encoding.h Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
- * (C) Copyright 2008-2009 Jakub Zawadzki <darkjames@darkjames.ath.cx>
- * Wojtek Kaniewski <wojtekka@irc.pl>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-#ifndef LIBGADU_ENCODING_H
-#define LIBGADU_ENCODING_H
-char *gg_encoding_convert(const char *src, gg_encoding_t src_encoding,
- gg_encoding_t dst_encoding, int src_length, int dst_length);
-#endif /* LIBGADU_SESSION_H */
--- a/libpurple/protocols/gg/lib/endian.c Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,109 +0,0 @@
- * (C) Copyright 2001-2010 Wojtek Kaniewski <wojtekka@irc.pl>
- * Robert J. Woźny <speedy@ziew.org>
- * Arkadiusz Miśkiewicz <arekm@pld-linux.org>
- * Tomasz Chiliński <chilek@chilan.com>
- * Adam Wysocki <gophi@ekg.chmurka.net>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
- * \brief Konwersja między różnymi kolejnościami bajtów
- * \internal Zamienia kolejność bajtów w 64-bitowym słowie.
- * Ze względu na little-endianowość protokołu Gadu-Gadu, na maszynach
- * big-endianowych odwraca kolejność bajtów w słowie.
- * \param x Liczba do zamiany
- * \return Liczba z odpowiednią kolejnością bajtów
-uint64_t gg_fix64(uint64_t x)
-#ifndef GG_CONFIG_BIGENDIAN
- (((x & (uint64_t) 0x00000000000000ffULL) << 56) |
- ((x & (uint64_t) 0x000000000000ff00ULL) << 40) |
- ((x & (uint64_t) 0x0000000000ff0000ULL) << 24) |
- ((x & (uint64_t) 0x00000000ff000000ULL) << 8) |
- ((x & (uint64_t) 0x000000ff00000000ULL) >> 8) |
- ((x & (uint64_t) 0x0000ff0000000000ULL) >> 24) |
- ((x & (uint64_t) 0x00ff000000000000ULL) >> 40) |
- ((x & (uint64_t) 0xff00000000000000ULL) >> 56));
- * \internal Zamienia kolejność bajtów w 32-bitowym słowie.
- * Ze względu na little-endianowość protokołu Gadu-Gadu, na maszynach
- * big-endianowych odwraca kolejność bajtów w słowie.
- * \param x Liczba do zamiany
- * \return Liczba z odpowiednią kolejnością bajtów
-uint32_t gg_fix32(uint32_t x)
-#ifndef GG_CONFIG_BIGENDIAN
- (((x & (uint32_t) 0x000000ffU) << 24) |
- ((x & (uint32_t) 0x0000ff00U) << 8) |
- ((x & (uint32_t) 0x00ff0000U) >> 8) |
- ((x & (uint32_t) 0xff000000U) >> 24));
- * \internal Zamienia kolejność bajtów w 16-bitowym słowie.
- * Ze względu na little-endianowość protokołu Gadu-Gadu, na maszynach
- * big-endianowych zamienia kolejność bajtów w słowie.
- * \param x Liczba do zamiany
- * \return Liczba z odpowiednią kolejnością bajtów
-uint16_t gg_fix16(uint16_t x)
-#ifndef GG_CONFIG_BIGENDIAN
- (((x & (uint16_t) 0x00ffU) << 8) |
- ((x & (uint16_t) 0xff00U) >> 8));
--- a/libpurple/protocols/gg/lib/events.c Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1901 +0,0 @@
- * (C) Copyright 2001-2006 Wojtek Kaniewski <wojtekka@irc.pl>
- * Robert J. Woźny <speedy@ziew.org>
- * Arkadiusz Miśkiewicz <arekm@pld-linux.org>
- * Adam Wysocki <gophi@ekg.chmurka.net>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
- * \brief Obsługa zdarzeń
- * \todo Poprawna obsługa gg_proxy_http_only
-#ifdef GG_CONFIG_HAVE_GNUTLS
-# include <gnutls/gnutls.h>
-# include <gnutls/x509.h>
-#ifdef GG_CONFIG_HAVE_OPENSSL
-# include <openssl/err.h>
-# include <openssl/x509.h>
-# include <openssl/rand.h>
- * Zwalnia pamięć zajmowaną przez informację o zdarzeniu.
- * Funkcję należy wywoływać za każdym razem gdy funkcja biblioteki zwróci
- * strukturę \c gg_event.
- * \param e Struktura zdarzenia
-void gg_event_free(struct gg_event *e)
- gg_debug(GG_DEBUG_FUNCTION, "** gg_event_free(%p);\n", e);
- case GG_EVENT_MULTILOGON_MSG:
- free(e->event.msg.message);
- free(e->event.msg.formats);
- free(e->event.msg.recipients);
- free(e->event.msg.xhtml_message);
- case GG_EVENT_NOTIFY60:
- for (i = 0; e->event.notify60[i].uin; i++)
- free(e->event.notify60[i].descr);
- free(e->event.notify60);
- case GG_EVENT_STATUS60:
- free(e->event.status60.descr);
- free(e->event.status.descr);
- case GG_EVENT_NOTIFY_DESCR:
- free(e->event.notify_descr.notify);
- free(e->event.notify_descr.descr);
- case GG_EVENT_DCC_VOICE_DATA:
- free(e->event.dcc_voice_data.data);
- case GG_EVENT_PUBDIR50_SEARCH_REPLY:
- case GG_EVENT_PUBDIR50_READ:
- case GG_EVENT_PUBDIR50_WRITE:
- gg_pubdir50_free(e->event.pubdir50);
- case GG_EVENT_USERLIST:
- free(e->event.userlist.reply);
- case GG_EVENT_IMAGE_REPLY:
- free(e->event.image_reply.filename);
- free(e->event.image_reply.image);
- case GG_EVENT_XML_EVENT:
- free(e->event.xml_event.data);
- case GG_EVENT_JSON_EVENT:
- free(e->event.json_event.data);
- free(e->event.json_event.type);
- case GG_EVENT_USER_DATA:
- for (i = 0; i < e->event.user_data.user_count; i++) {
- for (j = 0; j < e->event.user_data.users[i].attr_count; j++) {
- free(e->event.user_data.users[i].attrs[j].key);
- free(e->event.user_data.users[i].attrs[j].value);
- free(e->event.user_data.users[i].attrs);
- free(e->event.user_data.users);
- case GG_EVENT_MULTILOGON_INFO:
- for (i = 0; i < e->event.multilogon_info.count; i++)
- free(e->event.multilogon_info.sessions[i].name);
- free(e->event.multilogon_info.sessions);
- case GG_EVENT_USERLIST100_REPLY:
- free(e->event.userlist100_reply.reply);
- free(e->event.imtoken.imtoken);
- case GG_EVENT_CHAT_INFO:
- free(e->event.chat_info.participants);
- * \internal Usuwa obrazek z kolejki do wysłania.
- * \param s Struktura sesji
- * \param q Struktura obrazka
- * \param freeq Flaga zwolnienia elementu kolejki
- * \return 0 jeśli się powiodło, -1 jeśli wystąpił błąd
-int gg_image_queue_remove(struct gg_session *s, struct gg_image_queue *q, int freeq)
- struct gg_image_queue *qq;
- for (qq = s->images; qq; qq = qq->next) {
- * \internal Inicjalizuje struktury SSL.
- * \param gs Struktura sesji
- * \return 0 jeśli się powiodło, -1 jeśli wystąpił błąd
-int gg_session_init_ssl(struct gg_session *gs)
-#ifdef GG_CONFIG_HAVE_GNUTLS
- gg_session_gnutls_t *tmp;
- tmp = (gg_session_gnutls_t*) gs->ssl;
- tmp = malloc(sizeof(gg_session_gnutls_t));
- gg_debug(GG_DEBUG_MISC, "// gg_session_connect() out of memory for GnuTLS session\n");
- memset(tmp, 0, sizeof(gg_session_gnutls_t));
- gnutls_certificate_allocate_credentials(&tmp->xcred);
-#ifdef GG_CONFIG_SSL_SYSTEM_TRUST
-#ifdef HAVE_GNUTLS_CERTIFICATE_SET_X509_SYSTEM_TRUST
- gnutls_certificate_set_x509_system_trust(tmp->xcred);
- gnutls_certificate_set_x509_trust_file(tmp->xcred,
- GG_CONFIG_GNUTLS_SYSTEM_TRUST_STORE,
- gnutls_deinit(tmp->session);
- gnutls_init(&tmp->session, GNUTLS_CLIENT);
- gnutls_set_default_priority(tmp->session);
- gnutls_credentials_set(tmp->session, GNUTLS_CRD_CERTIFICATE, tmp->xcred);
- gnutls_transport_set_ptr(tmp->session, (gnutls_transport_ptr_t) (intptr_t) gs->fd);
-#ifdef GG_CONFIG_HAVE_OPENSSL
- OpenSSL_add_ssl_algorithms();
- rstruct.ptr = (void *) &rstruct;
- RAND_seed((void *) rdata, sizeof(rdata));
- RAND_seed((void *) &rstruct, sizeof(rstruct));
- if (gs->ssl_ctx == NULL) {
- gs->ssl_ctx = SSL_CTX_new(SSLv3_client_method());
- if (gs->ssl_ctx == NULL) {
- ERR_error_string_n(ERR_get_error(), buf, sizeof(buf));
- gg_debug(GG_DEBUG_MISC, "// gg_session_connect() SSL_CTX_new() failed: %s\n", buf);
- SSL_CTX_set_verify(gs->ssl_ctx, SSL_VERIFY_NONE, NULL);
-#ifdef GG_CONFIG_SSL_SYSTEM_TRUST
- SSL_CTX_set_default_verify_paths(gs->ssl_ctx);
- gs->ssl = SSL_new(gs->ssl_ctx);
- ERR_error_string_n(ERR_get_error(), buf, sizeof(buf));
- gg_debug(GG_DEBUG_MISC, "// gg_session_connect() SSL_new() failed: %s\n", buf);
- SSL_set_fd(gs->ssl, gs->fd);
- * \internal Funkcja próbuje wysłać dane zakolejkowane do wysyłki.
- * \param sess Struktura sesji
- * \return 0 jeśli się powiodło, -1 jeśli wystąpił błąd
-static int gg_send_queued_data(struct gg_session *sess)
- if (sess->send_buf == NULL || sess->send_left == 0)
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() sending %d bytes of queued data\n", sess->send_left);
- res = send(sess->fd, sess->send_buf, sess->send_left, 0);
- if (errno == EAGAIN || errno == EINTR) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd()"
- " non-critical send error (errno=%d, %s)\n",
- errno, strerror(errno));
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() send() "
- "failed (errno=%d, %s)\n", errno, strerror(errno));
- if (res == sess->send_left) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() sent all queued data\n");
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() sent %d"
- " bytes of queued data, %d bytes left\n",
- res, sess->send_left - res);
- memmove(sess->send_buf, sess->send_buf + res, sess->send_left - res);
- sess->send_left -= res;
- * \internal Sprawdza wynik połączenia asynchronicznego.
- * \param gs Struktura sesji
- * \param res_ptr Wskaźnik na kod błędu
- * \return 0 jeśli się powiodło, -1 jeśli wystąpił błąd
-static int gg_async_connect_failed(struct gg_session *gs, int *res_ptr)
- socklen_t res_size = sizeof(res);
- if (gs->timeout == 0) {
- if (getsockopt(gs->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) == -1) {
-typedef gg_action_t (*gg_state_handler_t)(struct gg_session *gs,
- struct gg_event *ge, enum gg_state_t next_state,
- enum gg_state_t alt_state, enum gg_state_t alt2_state);
- gg_state_handler_t handler;
- enum gg_state_t next_state;
- enum gg_state_t alt_state;
- enum gg_state_t alt2_state;
-} gg_state_transition_t;
- * 0 jeżeli nie ma ustawionego specjalnego managera gniazdek
- * 1 w przypadku powodzenia
-static int gg_handle_resolve_custom(struct gg_session *sess, enum gg_state_t next_state)
- struct gg_session_private *p = sess->private_data;
- if (p->socket_manager_type == GG_SOCKET_MANAGER_TYPE_INTERNAL)
- if (p->socket_manager.connect_cb == NULL) {
- gg_debug_session(sess, GG_DEBUG_MISC | GG_DEBUG_ERROR,
- "// gg_handle_resolve_custom() socket_manager.connect "
- "callback is empty\n");
- if (p->socket_handle != NULL) {
- gg_debug_session(sess, GG_DEBUG_MISC | GG_DEBUG_ERROR,
- "// gg_handle_resolve_custom() socket_handle is not "
- port = sess->connect_port[sess->connect_index];
- if (next_state == GG_STATE_SEND_HUB)
- if (sess->ssl_flag != GG_SSL_DISABLED &&
- next_state == GG_STATE_READING_KEY)
- /* XXX: w tej chwili nie ma możliwości łączenia się do HUBa po
- * SSL, ale może będzie w przyszłości */
- if (is_tls && p->socket_manager_type == GG_SOCKET_MANAGER_TYPE_TCP) {
- next_state = GG_STATE_TLS_NEGOTIATION;
- gg_debug_session(sess, GG_DEBUG_MISC | GG_DEBUG_ERROR,
- "// gg_handle_resolve_custom() port <= 0\n");
- p->socket_next_state = next_state;
- p->socket_handle = p->socket_manager.connect_cb(
- p->socket_manager.cb_data, sess->resolver_host, port, is_tls,
- if (p->socket_failure != 0) {
- if (p->socket_handle != NULL) {
- gg_debug_session(sess, GG_DEBUG_MISC | GG_DEBUG_WARNING,
- "// gg_handle_resolve_custom() handle should be"
- if (p->socket_handle == NULL) {
- gg_debug_session(sess, GG_DEBUG_MISC | GG_DEBUG_ERROR,
- "// gg_handle_resolve_custom() returned empty "
-static gg_action_t gg_handle_resolve_sync(struct gg_session *sess,
- struct gg_event *e, enum gg_state_t next_state,
- enum gg_state_t alt_state, enum gg_state_t alt2_state)
- res = gg_handle_resolve_custom(sess, alt_state);
- addr.s_addr = inet_addr(sess->resolver_host);
- if (addr.s_addr == INADDR_NONE) {
- struct in_addr *addr_list = NULL;
- unsigned int addr_count;
- if (gg_gethostbyname_real(sess->resolver_host, &addr_list, &addr_count, 0) == -1) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd()"
- " host %s not found\n", sess->resolver_host);
- e->event.failure = GG_FAILURE_RESOLVING;
- sess->resolver_result = addr_list;
- sess->resolver_count = addr_count;
- sess->resolver_index = 0;
- sess->resolver_result = malloc(sizeof(struct in_addr));
- if (sess->resolver_result == NULL) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() out of memory\n");
- sess->resolver_result[0].s_addr = addr.s_addr;
- sess->resolver_count = 1;
- sess->resolver_index = 0;
- sess->state = next_state;
-static gg_action_t gg_handle_resolve_async(struct gg_session *sess,
- struct gg_event *e, enum gg_state_t next_state,
- enum gg_state_t alt_state, enum gg_state_t alt2_state)
- res = gg_handle_resolve_custom(sess, alt_state);
- if (sess->resolver_start(&sess->fd, &sess->resolver, sess->resolver_host) == -1) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() "
- "resolving failed (errno=%d, %s)\n",
- errno, strerror(errno));
- e->event.failure = GG_FAILURE_RESOLVING;
- sess->state = next_state;
- sess->check = GG_CHECK_READ;
- sess->timeout = GG_DEFAULT_TIMEOUT;
-static gg_action_t gg_handle_resolving(struct gg_session *sess,
- struct gg_event *e, enum gg_state_t next_state,
- enum gg_state_t alt_state, enum gg_state_t alt2_state)
- res = gg_resolver_recv(sess->fd, buf, sizeof(buf));
- if (res == -1 && (errno == EAGAIN || errno == EINTR)) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() "
- "non-critical error (errno=%d, %s)\n",
- errno, strerror(errno));
- sess->resolver_cleanup(&sess->resolver, 0);
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() read "
- "error (errno=%d, %s)\n", errno, strerror(errno));
- e->event.failure = GG_FAILURE_RESOLVING;
- tmp = realloc(sess->recv_buf, sess->recv_done + res);
- memcpy(sess->recv_buf + sess->recv_done, buf, res);
- sess->recv_done += res;
- /* Sprawdź, czy mamy listę zakończoną INADDR_NONE */
- addrs = (struct in_addr *)(void *)sess->recv_buf;
- for (i = 0; i < sess->recv_done / sizeof(struct in_addr); i++) {
- if (addrs[i].s_addr == INADDR_NONE) {
- /* Nie znaleziono hosta */
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() host not found\n");
- e->event.failure = GG_FAILURE_RESOLVING;
- /* Nie mamy pełnej listy, ale połączenie zerwane */
- if (res == 0 && count == -1) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection broken\n");
- e->event.failure = GG_FAILURE_RESOLVING;
- /* Nie mamy pełnej listy, normalna sytuacja */
-#ifndef GG_DEBUG_DISABLE
- if ((gg_debug_level & GG_DEBUG_DUMP) && (count > 0)) {
- for (i = 0; i < (unsigned int) count; i++) {
- len += strlen(inet_ntoa(addrs[i]));
- list = malloc(len + 1);
- for (i = 0; i < (unsigned int) count; i++) {
- strcat(list, inet_ntoa(addrs[i]));
- gg_debug_session(sess, GG_DEBUG_DUMP, "// gg_watch_fd() resolved: %s\n", list);
- sess->state = next_state;
- sess->resolver_result = addrs;
- sess->resolver_count = count;
- sess->resolver_index = 0;
-static gg_action_t gg_handle_connect(struct gg_session *sess,
- struct gg_event *e, enum gg_state_t next_state,
- enum gg_state_t alt_state, enum gg_state_t alt2_state)
- if (sess->resolver_index >= sess->resolver_count) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() out of addresses to connect to\n");
- e->event.failure = GG_FAILURE_CONNECTING;
- addr = sess->resolver_result[sess->resolver_index];
- if (sess->state == GG_STATE_CONNECT_HUB) {
- sess->hub_addr = addr.s_addr;
- sess->proxy_addr = addr.s_addr;
- port = sess->proxy_port;
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connecting to %s:%d\n", inet_ntoa(addr), port);
- sess->fd = gg_connect(&addr, port, sess->async);
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() "
- "connection failed (errno=%d, %s)\n",
- errno, strerror(errno));
- sess->resolver_index++;
- sess->state = next_state;
- sess->check = GG_CHECK_WRITE;
- sess->timeout = GG_DEFAULT_TIMEOUT;
- sess->soft_timeout = 1;
-static gg_action_t gg_handle_connecting(struct gg_session *sess,
- struct gg_event *e, enum gg_state_t next_state,
- enum gg_state_t alt_state, enum gg_state_t alt2_state)
- sess->soft_timeout = 0;
- if (gg_async_connect_failed(sess, &res)) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() "
- "connection failed (errno=%d, %s)\n",
- sess->resolver_index++;
- sess->state = alt_state;
- /* Z proxy zwykle łączymy się dwa razy, więc nie zwalniamy
- * adresów IP po pierwszym połączeniu. */
- if (sess->state != GG_STATE_CONNECTING_PROXY_HUB) {
- free(sess->resolver_result);
- sess->resolver_result = NULL;
- sess->state = next_state;
-static gg_action_t gg_handle_connect_gg(struct gg_session *sess,
- struct gg_event *e, enum gg_state_t next_state,
- enum gg_state_t alt_state, enum gg_state_t alt2_state)
- gg_debug_session(sess, GG_DEBUG_MISC, "resolver_index=%d, "
- "connect_index=%d, connect_port={%d,%d}\n",
- sess->resolver_index, sess->connect_index,
- sess->connect_port[0], sess->connect_port[1]);
- if ((unsigned int) sess->connect_index >=
- sizeof(sess->connect_port) / sizeof(sess->connect_port[0]) ||
- sess->connect_port[sess->connect_index] == 0)
- sess->connect_index = 0;
- sess->resolver_index++;
- if (sess->resolver_index >= sess->resolver_count) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() out of addresses to connect to\n");
- e->event.failure = GG_FAILURE_CONNECTING;
- addr = sess->resolver_result[sess->resolver_index];
- port = sess->connect_port[sess->connect_index];
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connecting to %s:%d\n", inet_ntoa(addr), port);
- sess->server_addr = addr.s_addr;
- sess->fd = gg_connect(&addr, port, sess->async);
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() "
- "connection failed (errno=%d, %s)\n",
- errno, strerror(errno));
- sess->state = next_state;
- sess->check = GG_CHECK_WRITE;
- sess->timeout = GG_DEFAULT_TIMEOUT;
- sess->soft_timeout = 1;
-static gg_action_t gg_handle_connecting_gg(struct gg_session *sess,
- struct gg_event *e, enum gg_state_t next_state,
- enum gg_state_t alt_state, enum gg_state_t alt2_state)
- sess->soft_timeout = 0;
- /* jeśli wystąpił błąd podczas łączenia się... */
- if (gg_async_connect_failed(sess, &res)) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() "
- "connection failed (errno=%d, %s)\n",
- sess->state = alt_state;
- free(sess->resolver_result);
- sess->resolver_result = NULL;
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connected\n");
- if (sess->ssl_flag != GG_SSL_DISABLED) {
- if (gg_session_init_ssl(sess) == -1) {
- e->event.failure = GG_FAILURE_TLS;
- sess->state = alt2_state;
- sess->check = GG_CHECK_WRITE;
- sess->timeout = GG_DEFAULT_TIMEOUT;
- sess->state = next_state;
- sess->check = GG_CHECK_READ;
- sess->timeout = GG_DEFAULT_TIMEOUT;
-static gg_action_t gg_handle_send_hub(struct gg_session *sess,
- struct gg_event *e, enum gg_state_t next_state,
- enum gg_state_t alt_state, enum gg_state_t alt2_state)
- char *req, *client, *auth;
- if (sess->client_version != NULL && isdigit(sess->client_version[0]))
- client = gg_urlencode(sess->client_version);
- else if (sess->protocol_version <= GG_PROTOCOL_VERSION_100)
- client = gg_urlencode(GG_DEFAULT_CLIENT_VERSION_100);
- else /* sess->protocol_version >= GG_PROTOCOL_VERSION_110 */
- client = gg_urlencode(GG_DEFAULT_CLIENT_VERSION_110);
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() out of memory for client version\n");
- if (sess->proxy_addr && sess->proxy_port) {
- host = "http://" GG_APPMSG_HOST;
- auth = gg_proxy_auth();
- if (sess->ssl_flag != GG_SSL_DISABLED) {
- ("GET %s/appsvc/appmsg_ver10.asp?fmnumber=%u&fmt=2&"
- "lastmsg=%d&version=%s&age=2&gender=1 HTTP/1.0\r\n"
- "Connection: close\r\n"
- "Host: " GG_APPMSG_HOST "\r\n"
- "\r\n", host, sess->uin, sess->last_sysmsg, client, (auth) ? auth : "");
- ("GET %s/appsvc/appmsg_ver8.asp?fmnumber=%u&fmt=2&lastmsg=%d&version=%s HTTP/1.0\r\n"
- "Host: " GG_APPMSG_HOST "\r\n"
- "\r\n", host, sess->uin, sess->last_sysmsg, client, (auth) ? auth : "");
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() out of memory\n");
- e->event.failure = GG_FAILURE_PROXY;
- gg_debug_session(sess, GG_DEBUG_TRAFFIC, "// sending http query:\n%s", req);
- res = send(sess->fd, req, req_len, 0);
- if (res == -1 && errno != EINTR && errno != EAGAIN) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() sending query failed\n");
- e->event.failure = (!proxy) ? GG_FAILURE_HUB : GG_FAILURE_PROXY;
- if ((size_t) res < req_len) {
- sess->state = alt_state;
- sess->check = GG_CHECK_WRITE;
- sess->timeout = GG_DEFAULT_TIMEOUT;
- sess->state = next_state;
- sess->check = GG_CHECK_READ;
- sess->timeout = GG_DEFAULT_TIMEOUT;
-static gg_action_t gg_handle_sending_hub_proxy(struct gg_session *sess,
- struct gg_event *e, enum gg_state_t next_state,
- enum gg_state_t alt_state, enum gg_state_t alt2_state)
- if (gg_send_queued_data(sess) == -1) {
- e->event.failure = GG_FAILURE_WRITING;
- if (sess->send_left > 0)
- sess->state = next_state;
- sess->check = GG_CHECK_READ;
- sess->timeout = GG_DEFAULT_TIMEOUT;
-static gg_action_t gg_handle_reading_hub_proxy(struct gg_session *sess,
- struct gg_event *e, enum gg_state_t next_state,
- enum gg_state_t alt_state, enum gg_state_t alt2_state)
- char buf[1024], *tmp, host[129];
- int port = GG_DEFAULT_PORT;
- char *host_white_default[] = GG_DEFAULT_HOST_WHITE_LIST;
- res = recv(sess->fd, buf, sizeof(buf), 0);
- if (res == -1 && (errno == EAGAIN || errno == EINTR)) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() "
- "non-critical recv error (errno=%d, %s)\n",
- errno, strerror(errno));
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() recv "
- "error (errno=%d, %s)\n", errno, strerror(errno));
- e->event.failure = GG_FAILURE_CONNECTING;
- tmp = realloc(sess->recv_buf, sess->recv_done + res + 1);
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() not enough memory for http reply\n");
- memcpy(sess->recv_buf + sess->recv_done, buf, res);
- sess->recv_done += res;
- sess->recv_buf[sess->recv_done] = 0;
- if (res == 0 && sess->recv_buf == NULL) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection closed\n");
- e->event.failure = GG_FAILURE_CONNECTING;
- gg_debug_session(sess, GG_DEBUG_TRAFFIC, "// received http reply:\n%s", sess->recv_buf);
- res = sscanf(sess->recv_buf, "HTTP/1.%*d %3d ", &reply);
- /* sprawdzamy, czy wszystko w porządku. */
- if (res != 1 || reply != 200) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() invalid http reply, connection failed\n");
- e->event.failure = GG_FAILURE_CONNECTING;
- /* szukamy początku treści */
- body = strstr(sess->recv_buf, "\r\n\r\n");
- body = strstr(sess->recv_buf, "\n\n");
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() can't find body\n");
- e->event.failure = GG_FAILURE_CONNECTING;
- /* 17591 0 91.197.13.71:8074 91.197.13.71 */
- res = sscanf(body, "%d %*d %128s", &reply, host);
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() invalid hub reply, connection failed\n");
- e->event.failure = GG_FAILURE_CONNECTING;
- gg_debug_session(sess, GG_DEBUG_MISC, "reply=%d, host=\"%s\"\n", reply, host);
- /* jeśli pierwsza liczba w linii nie jest równa zeru,
- * oznacza to, że mamy wiadomość systemową. */
- tmp = strchr(body, '\n');
- e->type = GG_EVENT_MSG;
- e->event.msg.msgclass = reply;
- e->event.msg.sender = 0;
- e->event.msg.message = (unsigned char*) strdup(tmp + 1);
- if (e->event.msg.message == NULL) {
- gg_debug_session(sess, GG_DEBUG_MISC,
- "// gg_watch_fd() not enough memory "
- "for system message\n");
- tmp = strchr(host, ':');
- if (strcmp(host, "notoperating") == 0) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() service unavailable\n");
- e->event.failure = GG_FAILURE_UNAVAILABLE;
- addr.s_addr = inet_addr(host);
- if (addr.s_addr == INADDR_NONE)
- sess->server_addr = addr.s_addr;
- if (sess->state != GG_STATE_READING_PROXY_HUB) {
- sess->connect_port[0] = port;
- sess->connect_port[1] = (port != GG_HTTPS_PORT) ? GG_HTTPS_PORT : 0;
- sess->connect_port[0] = sess->port;
- sess->connect_port[1] = 0;
- sess->connect_port[0] = (sess->port == 0) ? GG_HTTPS_PORT : sess->port;
- sess->connect_port[1] = 0;
- free(sess->connect_host);
- sess->connect_host = strdup(host);
- if (sess->connect_host == NULL) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() not enough memory\n");
- host_white = sess->private_data->host_white_list;
- host_white = host_white_default;
- if (sess->ssl_flag == GG_SSL_REQUIRED && host_white[0] != NULL) {
- host_len = strlen(sess->connect_host);
- for (it = host_white; *it != NULL; it++) {
- const char *white = *it;
- int white_len, dom_offset;
- white_len = strlen(white);
- if (white_len > host_len)
- dom_offset = host_len - white_len;
- if (strncasecmp(sess->connect_host + dom_offset, white,
- if (white_len < host_len) {
- if (sess->connect_host[dom_offset - 1] != '.')
- gg_debug_session(sess, GG_DEBUG_MISC | GG_DEBUG_ERROR,
- "// gg_watch_fd() the HUB server returned "
- "a host that is not trusted (%s)\n",
- e->event.failure = GG_FAILURE_TLS;
- if (sess->state == GG_STATE_READING_HUB)
- sess->resolver_host = sess->connect_host;
- /* Jeśli łączymy się przez proxy, zacznijmy od początku listy */
- sess->resolver_index = 0;
- sess->state = (sess->async) ? next_state : alt_state;
-static gg_action_t gg_handle_send_proxy_gg(struct gg_session *sess,
- struct gg_event *e, enum gg_state_t next_state,
- enum gg_state_t alt_state, enum gg_state_t alt2_state)
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() %s\n", gg_debug_state(sess->state));
- if (sess->connect_index > 1 || sess->connect_port[sess->connect_index] == 0) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() out of connection candidates\n");
- e->event.failure = GG_FAILURE_CONNECTING;
- auth = gg_proxy_auth();
- req = gg_saprintf("CONNECT %s:%d HTTP/1.0\r\n%s\r\n",
- sess->connect_host, sess->connect_port[sess->connect_index],
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() out of memory\n");
- e->event.failure = GG_FAILURE_PROXY;
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() proxy request:\n%s", req);
- res = send(sess->fd, req, req_len, 0);
- if (res == -1 && errno != EINTR && errno != EAGAIN) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() sending query failed\n");
- e->event.failure = GG_FAILURE_PROXY;
- if ((size_t) res < req_len) {
- sess->state = alt_state;
- sess->check = GG_CHECK_WRITE;
- sess->timeout = GG_DEFAULT_TIMEOUT;
- sess->state = next_state;
- sess->check = GG_CHECK_READ;
- sess->timeout = GG_DEFAULT_TIMEOUT;
-static gg_action_t gg_handle_tls_negotiation(struct gg_session *sess,
- struct gg_event *e, enum gg_state_t next_state,
- enum gg_state_t alt_state, enum gg_state_t alt2_state)
-#if defined(GG_CONFIG_HAVE_GNUTLS) || defined(GG_CONFIG_HAVE_OPENSSL)
- int valid_hostname = 0;
-#ifdef GG_CONFIG_HAVE_GNUTLS
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_TLS_NEGOTIATION\n");
- res = gnutls_handshake(GG_SESSION_GNUTLS(sess));
- if (res == GNUTLS_E_AGAIN) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() TLS handshake GNUTLS_E_AGAIN\n");
- if (gnutls_record_get_direction(GG_SESSION_GNUTLS(sess)) == 0)
- sess->check = GG_CHECK_READ;
- sess->check = GG_CHECK_WRITE;
- sess->timeout = GG_DEFAULT_TIMEOUT;
- if (res == GNUTLS_E_INTERRUPTED) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() TLS handshake GNUTLS_E_INTERRUPTED\n");
- if (res != GNUTLS_E_SUCCESS) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd()"
- " TLS handshake error: %d, %s\n",
- res, gnutls_strerror(res));
- e->event.failure = GG_FAILURE_TLS;
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() TLS negotiation succeded:\n");
- gg_debug_session(sess, GG_DEBUG_MISC, "// cipher: VERS-%s:%s:%s:%s:COMP-%s\n",
- gnutls_protocol_get_name(gnutls_protocol_get_version(GG_SESSION_GNUTLS(sess))),
- gnutls_cipher_get_name(gnutls_cipher_get(GG_SESSION_GNUTLS(sess))),
- gnutls_kx_get_name(gnutls_kx_get(GG_SESSION_GNUTLS(sess))),
- gnutls_mac_get_name(gnutls_mac_get(GG_SESSION_GNUTLS(sess))),
- gnutls_compression_get_name(gnutls_compression_get(GG_SESSION_GNUTLS(sess))));
- if (gnutls_certificate_type_get(GG_SESSION_GNUTLS(sess)) == GNUTLS_CRT_X509) {
- unsigned int peer_count;
- const gnutls_datum_t *peers;
- gnutls_x509_crt_t cert;
- if (gnutls_x509_crt_init(&cert) == 0) {
- peers = gnutls_certificate_get_peers(GG_SESSION_GNUTLS(sess), &peer_count);
- if (gnutls_x509_crt_import(cert, &peers[0], GNUTLS_X509_FMT_DER) == 0) {
- gnutls_x509_crt_get_dn(cert, buf, &size);
- gg_debug_session(sess, GG_DEBUG_MISC, "// cert subject: %s\n", buf);
- gnutls_x509_crt_get_issuer_dn(cert, buf, &size);
- gg_debug_session(sess, GG_DEBUG_MISC, "// cert issuer: %s\n", buf);
- if (gnutls_x509_crt_check_hostname(cert, sess->connect_host) != 0)
- gnutls_x509_crt_deinit(cert);
- res = gnutls_certificate_verify_peers2(GG_SESSION_GNUTLS(sess), &status);
- if (res != 0 || status != 0) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// WARNING! unable to"
- " verify peer certificate: 0x%x, %d, %s\n", status, res,
- if (sess->ssl_flag == GG_SSL_REQUIRED) {
- e->event.failure = GG_FAILURE_TLS;
- gg_debug_session(sess, GG_DEBUG_MISC, "// verified peer certificate\n");
-#elif defined GG_CONFIG_HAVE_OPENSSL
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() %s\n", gg_debug_state(sess->state));
- res = SSL_connect(GG_SESSION_OPENSSL(sess));
- err = SSL_get_error(GG_SESSION_OPENSSL(sess), res);
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() disconnected during TLS negotiation\n");
- e->event.failure = GG_FAILURE_TLS;
- if (err == SSL_ERROR_WANT_READ) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() SSL_connect() wants to read\n");
- sess->check = GG_CHECK_READ;
- sess->timeout = GG_DEFAULT_TIMEOUT;
- } else if (err == SSL_ERROR_WANT_WRITE) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() SSL_connect() wants to write\n");
- sess->check = GG_CHECK_WRITE;
- sess->timeout = GG_DEFAULT_TIMEOUT;
- ERR_error_string_n(ERR_get_error(), buf, sizeof(buf));
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() SSL_connect() bailed out: %s\n", buf);
- e->event.failure = GG_FAILURE_TLS;
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() TLS negotiation"
- " succeded:\n// cipher: %s\n",
- SSL_get_cipher_name(GG_SESSION_OPENSSL(sess)));
- peer = SSL_get_peer_certificate(GG_SESSION_OPENSSL(sess));
- gg_debug_session(sess, GG_DEBUG_MISC, "// WARNING! unable to get peer certificate!\n");
- if (sess->ssl_flag == GG_SSL_REQUIRED) {
- e->event.failure = GG_FAILURE_TLS;
- X509_NAME_oneline(X509_get_subject_name(peer), buf, sizeof(buf));
- gg_debug_session(sess, GG_DEBUG_MISC, "// cert subject: %s\n", buf);
- X509_NAME_oneline(X509_get_issuer_name(peer), buf, sizeof(buf));
- gg_debug_session(sess, GG_DEBUG_MISC, "// cert issuer: %s\n", buf);
- res = SSL_get_verify_result(GG_SESSION_OPENSSL(sess));
- if (res != X509_V_OK) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// WARNING! "
- "unable to verify peer certificate! "
- if (sess->ssl_flag == GG_SSL_REQUIRED) {
- e->event.failure = GG_FAILURE_TLS;
- gg_debug_session(sess, GG_DEBUG_MISC, "// verified peer certificate\n");
- if (X509_NAME_get_text_by_NID(X509_get_subject_name(peer), NID_commonName, buf, sizeof(buf)) == -1)
- /* Obsługa certyfikatów z wieloznacznikiem */
- if (strchr(buf, '*') == buf && strchr(buf + 1, '*') == NULL) {
- tmp = strchr(sess->connect_host, '.');
- valid_hostname = (strcasecmp(tmp, buf + 1) == 0);
- valid_hostname = (strcasecmp(sess->connect_host, buf) == 0);
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() no SSL support\n");
- e->event.failure = GG_FAILURE_TLS;
-#if defined(GG_CONFIG_HAVE_GNUTLS) || defined(GG_CONFIG_HAVE_OPENSSL)
- gg_debug_session(sess, GG_DEBUG_MISC, "// WARNING! unable to verify hostname\n");
- if (sess->ssl_flag == GG_SSL_REQUIRED) {
- e->event.failure = GG_FAILURE_TLS;
- sess->state = next_state;
- sess->check = GG_CHECK_READ;
- sess->timeout = GG_DEFAULT_TIMEOUT;
-static gg_action_t gg_handle_reading_proxy_gg(struct gg_session *sess,
- struct gg_event *e, enum gg_state_t next_state,
- enum gg_state_t alt_state, enum gg_state_t alt2_state)
- res = recv(sess->fd, buf, sizeof(buf), 0);
- gg_debug_session(sess, GG_DEBUG_MISC, "recv() = %d\n", res);
- if (res == -1 && (errno == EAGAIN || errno == EINTR)) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() "
- "non-critical recv error (errno=%d, %s)\n",
- errno, strerror(errno));
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() recv "
- "error (errno=%d, %s)\n", errno, strerror(errno));
- e->event.failure = GG_FAILURE_CONNECTING;
- tmp = realloc(sess->recv_buf, sess->recv_done + res + 1);
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() not enough memory for http reply\n");
- memcpy(sess->recv_buf + sess->recv_done, buf, res);
- sess->recv_done += res;
- sess->recv_buf[sess->recv_done] = 0;
- if (res == 0 && sess->recv_buf == NULL) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection closed\n");
- e->event.failure = GG_FAILURE_CONNECTING;
- /* szukamy początku treści */
- body = strstr(sess->recv_buf, "\r\n\r\n");
- body = strstr(sess->recv_buf, "\n\n");
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() can't find body\n");
- e->event.failure = GG_FAILURE_CONNECTING;
- gg_debug_session(sess, GG_DEBUG_MISC, "// found body!\n");
- gg_debug_session(sess, GG_DEBUG_TRAFFIC, "// received proxy reply:\n%s\n", sess->recv_buf);
- res = sscanf(sess->recv_buf, "HTTP/1.%*d %3d ", &reply);
- gg_debug_session(sess, GG_DEBUG_MISC, "res = %d, reply = %d\n", res, reply);
- /* sprawdzamy, czy wszystko w porządku. */
- if (res != 1 || reply != 200) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() invalid http reply, connection failed\n");
- e->event.failure = GG_FAILURE_CONNECTING;
- if (sess->ssl_flag != GG_SSL_DISABLED) {
- if (gg_session_init_ssl(sess) == -1) {
- e->event.failure = GG_FAILURE_TLS;
- /* Teoretycznie SSL jest inicjowany przez klienta, więc serwer
- * nie powinien niczego wysłać. */
- if (sess->recv_buf + sess->recv_done > body) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() unexpected SSL data\n");
- e->event.failure = GG_FAILURE_TLS;
- sess->state = alt_state;
- sess->check = GG_CHECK_WRITE;
- sess->timeout = GG_DEFAULT_TIMEOUT;
- sess->state = next_state;
- sess->check = GG_CHECK_READ;
- sess->timeout = GG_DEFAULT_TIMEOUT; /* Pierwszy pakiet musi przyjść */
- /* Jeśli zbuforowaliśmy za dużo, przeanalizuj */
- if (sess->recv_buf + sess->recv_done > body) {
- sess->recv_done = sess->recv_done - (body - sess->recv_buf);
- memmove(sess->recv_buf, body, sess->recv_done);
- sess->state = alt2_state;
-static gg_action_t gg_handle_connected(struct gg_session *sess,
- struct gg_event *e, enum gg_state_t next_state,
- enum gg_state_t alt_state, enum gg_state_t alt2_state)
- if (gg_send_queued_data(sess) == -1)
- res = gg_read(sess, buf, sizeof(buf));
- if (res == -1 && (errno == EAGAIN || errno == EINTR)) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() "
- "non-critical read error (errno=%d, %s)\n",
- errno, strerror(errno));
- if (res == -1 || res == 0) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd()"
- " read error (errno=%d, %s)\n",
- errno, strerror(errno));
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd()"
- " connection closed\n");
- if (sess->state == GG_STATE_DISCONNECTING && res == 0) {
- e->type = GG_EVENT_DISCONNECT_ACK;
- } else if (sess->state == GG_STATE_READING_KEY) {
- e->event.failure = GG_FAILURE_INVALID;
- gg_debug_dump(sess, GG_DEBUG_DUMP, buf, res);
- if (gg_session_handle_data(sess, buf, res, e) == -1)
- if (sess->send_buf != NULL)
- sess->check |= GG_CHECK_WRITE;
- if (gg_send_queued_data(sess) == -1)
- gh = gg_recv_packet(sess);
- if (sess->state == GG_STATE_DISCONNECTING) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection broken expectedly\n");
- e->type = GG_EVENT_DISCONNECT_ACK;
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd()"
- " gg_recv_packet failed (errno=%d, %s)\n",
- errno, strerror(errno));
- if (gg_session_handle_packet(sess, gh->type,
- (const char *) gh + sizeof(struct gg_header),
- sess->check = GG_CHECK_READ;
- if (sess->send_buf != NULL)
- sess->check |= GG_CHECK_WRITE;
-static gg_action_t gg_handle_error(struct gg_session *sess, struct gg_event *e,
- enum gg_state_t next_state, enum gg_state_t alt_state,
- enum gg_state_t alt2_state)
- struct gg_session_private *p = sess->private_data;
- gg_debug_session(sess, GG_DEBUG_MISC | GG_DEBUG_ERROR, "// gg_handle_error() failure=%d\n", p->socket_failure);
- e->event.failure = p->socket_failure;
-static const gg_state_transition_t handlers[] =
- /* style:maxlinelength:start-ignore */
- { GG_STATE_RESOLVE_HUB_SYNC, gg_handle_resolve_sync, GG_STATE_CONNECT_HUB, GG_STATE_SEND_HUB, 0 },
- { GG_STATE_RESOLVE_GG_SYNC, gg_handle_resolve_sync, GG_STATE_CONNECT_GG, GG_STATE_READING_KEY, 0 },
- { GG_STATE_RESOLVE_PROXY_HUB_SYNC, gg_handle_resolve_sync, GG_STATE_CONNECT_PROXY_HUB, GG_STATE_SEND_PROXY_HUB, 0 },
- { GG_STATE_RESOLVE_PROXY_GG_SYNC, gg_handle_resolve_sync, GG_STATE_CONNECT_PROXY_GG, GG_STATE_SEND_PROXY_GG, 0 },
- { GG_STATE_RESOLVE_HUB_ASYNC, gg_handle_resolve_async, GG_STATE_RESOLVING_HUB, GG_STATE_SEND_HUB, 0 },
- { GG_STATE_RESOLVE_GG_ASYNC, gg_handle_resolve_async, GG_STATE_RESOLVING_GG, GG_STATE_READING_KEY, 0 },
- { GG_STATE_RESOLVE_PROXY_HUB_ASYNC, gg_handle_resolve_async, GG_STATE_RESOLVING_PROXY_HUB, GG_STATE_SEND_PROXY_HUB, 0 },
- { GG_STATE_RESOLVE_PROXY_GG_ASYNC, gg_handle_resolve_async, GG_STATE_RESOLVING_PROXY_GG, GG_STATE_SEND_PROXY_GG, 0 },
- { GG_STATE_RESOLVING_HUB, gg_handle_resolving, GG_STATE_CONNECT_HUB, 0, 0 },
- { GG_STATE_RESOLVING_GG, gg_handle_resolving, GG_STATE_CONNECT_GG, 0, 0 },
- { GG_STATE_RESOLVING_PROXY_HUB, gg_handle_resolving, GG_STATE_CONNECT_PROXY_HUB, 0, 0 },
- { GG_STATE_RESOLVING_PROXY_GG, gg_handle_resolving, GG_STATE_CONNECT_PROXY_GG, 0, 0 },
- { GG_STATE_CONNECT_HUB, gg_handle_connect, GG_STATE_CONNECTING_HUB, 0, 0 },
- { GG_STATE_CONNECT_PROXY_HUB, gg_handle_connect, GG_STATE_CONNECTING_PROXY_HUB, 0, 0 },
- { GG_STATE_CONNECT_PROXY_GG, gg_handle_connect, GG_STATE_CONNECTING_PROXY_GG, 0, 0 },
- { GG_STATE_CONNECT_GG, gg_handle_connect_gg, GG_STATE_CONNECTING_GG, 0, 0 },
- { GG_STATE_CONNECTING_HUB, gg_handle_connecting, GG_STATE_SEND_HUB, GG_STATE_CONNECT_HUB, 0 },
- { GG_STATE_CONNECTING_PROXY_HUB, gg_handle_connecting, GG_STATE_SEND_PROXY_HUB, GG_STATE_CONNECT_PROXY_HUB, 0 },
- { GG_STATE_CONNECTING_PROXY_GG, gg_handle_connecting, GG_STATE_SEND_PROXY_GG, GG_STATE_CONNECT_PROXY_GG, 0 },
- { GG_STATE_CONNECTING_GG, gg_handle_connecting_gg, GG_STATE_READING_KEY, GG_STATE_CONNECT_GG, GG_STATE_TLS_NEGOTIATION },
- { GG_STATE_SEND_HUB, gg_handle_send_hub, GG_STATE_READING_HUB, GG_STATE_SENDING_HUB, 0 },
- { GG_STATE_SEND_PROXY_HUB, gg_handle_send_hub, GG_STATE_READING_PROXY_HUB, GG_STATE_SENDING_PROXY_HUB, 0 },
- { GG_STATE_SEND_PROXY_GG, gg_handle_send_proxy_gg, GG_STATE_READING_PROXY_GG, GG_STATE_SENDING_PROXY_GG, 0 },
- { GG_STATE_SENDING_HUB, gg_handle_sending_hub_proxy, GG_STATE_READING_HUB, 0, 0 },
- { GG_STATE_SENDING_PROXY_HUB, gg_handle_sending_hub_proxy, GG_STATE_READING_PROXY_HUB, 0, 0 },
- { GG_STATE_SENDING_PROXY_GG, gg_handle_sending_hub_proxy, GG_STATE_READING_PROXY_GG, 0, 0 },
- { GG_STATE_READING_HUB, gg_handle_reading_hub_proxy, GG_STATE_RESOLVE_GG_ASYNC, GG_STATE_RESOLVE_GG_SYNC, 0 },
- { GG_STATE_READING_PROXY_HUB, gg_handle_reading_hub_proxy, GG_STATE_CONNECT_PROXY_GG, GG_STATE_CONNECT_PROXY_GG, 0 },
- { GG_STATE_READING_PROXY_GG, gg_handle_reading_proxy_gg, GG_STATE_READING_KEY, GG_STATE_TLS_NEGOTIATION, GG_STATE_READING_KEY },
- { GG_STATE_TLS_NEGOTIATION, gg_handle_tls_negotiation, GG_STATE_READING_KEY, 0, 0 },
- { GG_STATE_READING_KEY, gg_handle_connected, 0, 0, 0 },
- { GG_STATE_READING_REPLY, gg_handle_connected, 0, 0, 0 },
- { GG_STATE_CONNECTED, gg_handle_connected, 0, 0, 0 },
- { GG_STATE_DISCONNECTING, gg_handle_connected, 0, 0, 0 },
- { GG_STATE_ERROR, gg_handle_error, 0, 0, 0 },
- /* style:maxlinelength:end-ignore */
-struct gg_event *gg_eventqueue_add(struct gg_session *sess)
- gg_eventqueue_t *queue_el, *it;
- queue_el = gg_new0(sizeof(gg_eventqueue_t));
- ge = gg_new0(sizeof(struct gg_event));
- if (queue_el == NULL || ge == NULL) {
- ge->type = GG_EVENT_NONE;
- if (sess->private_data->event_queue == NULL)
- sess->private_data->event_queue = queue_el;
- it = sess->private_data->event_queue;
- while (it->next != NULL)
- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze sesji.
- * Funkcja zwraca strukturę zdarzenia \c gg_event. Jeśli rodzaj zdarzenia
- * to \c GG_EVENT_NONE, nie wydarzyło się jeszcze nic wartego odnotowania.
- * Strukturę zdarzenia należy zwolnić funkcja \c gg_event_free().
- * \param sess Struktura sesji
- * \return Struktura zdarzenia lub \c NULL jeśli wystąpił błąd
-struct gg_event *gg_watch_fd(struct gg_session *sess)
- struct gg_session_private *priv;
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_watch_fd(%p);\n", sess);
- priv = sess->private_data;
- if (priv->event_queue != NULL) {
- ge = priv->event_queue->event;
- next = priv->event_queue->next;
- free(priv->event_queue);
- priv->event_queue = next;
- sess->check = priv->check_after_queue;
- sess->fd = priv->fd_after_queue;
- ge = malloc(sizeof(struct gg_event));
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() not enough memory for event data\n");
- memset(ge, 0, sizeof(struct gg_event));
- ge->type = GG_EVENT_NONE;
- unsigned int i, found = 0;
- for (i = 0; i < sizeof(handlers) / sizeof(handlers[0]); i++) {
- if (handlers[i].state == (enum gg_state_t) sess->state) {
- gg_debug_session(sess, GG_DEBUG_MISC,
- "// gg_watch_fd() %s\n",
- gg_debug_state(sess->state));
- res = (*handlers[i].handler)(sess, ge,
- handlers[i].next_state,
- handlers[i].alt2_state);
- gg_debug_session(sess, GG_DEBUG_MISC | GG_DEBUG_ERROR,
- "// gg_watch_fd() invalid state %s\n",
- gg_debug_state(sess->state));
- ge->event.failure = GG_FAILURE_INTERNAL;
- if (!sess->async && ge->type == GG_EVENT_NONE && res == GG_ACTION_WAIT)
- if (priv->event_queue != NULL) {
- priv->fd_after_queue = sess->fd;
- priv->check_after_queue = sess->check;
- /* wymuszamy ponowne wywołanie gg_watch_fd */
- sess->fd = gg_get_dummy_fd(sess);
- sess->fd = priv->fd_after_queue;
- sess->check = GG_CHECK_READ | GG_CHECK_WRITE;
- sess->state = GG_STATE_IDLE;
- if (ge->event.failure != 0) {
- ge->type = GG_EVENT_CONN_FAILED;
- /* Celowo nie ma default */
- * c-indentation-style: k&r
- * indent-tabs-mode: notnil
--- a/libpurple/protocols/gg/lib/fileio.h Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
- * (C) Copyright 2011 Bartosz Brachaczek <b.brachaczek@gmail.com>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
- * \brief Makra zapewniające kompatybilność API do obsługi operacji na plikach na różnych systemach
-#ifndef LIBGADU_FILEIO_H
-#define LIBGADU_FILEIO_H
-# define gg_file_close _close
-# define gg_file_close close
-# define S_IWUSR S_IWRITE
-#endif /* LIBGADU_FILEIO_H */
--- a/libpurple/protocols/gg/lib/handlers.c Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2881 +0,0 @@
- * (C) Copyright 2001-2011 Wojtek Kaniewski <wojtekka@irc.pl>
- * Robert J. Woźny <speedy@ziew.org>
- * Arkadiusz Miśkiewicz <arekm@pld-linux.org>
- * Tomasz Chiliński <chilek@chilan.com>
- * Adam Wysocki <gophi@ekg.chmurka.net>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
- * \brief Funkcje obsługi przychodzących pakietów
-#include "packets.pb-c.h"
-/* Ograniczenie długości listy kontaktów
- * z pakietów GG_USERLIST_REPLY do 10MB. */
-#define GG_USERLIST_REPLY_MAX_LENGTH 10485760
- * \internal Struktura opisująca funkcję obsługi pakietu.
- /* Stan w którym pakiet jest obsługiwany */
- /* Minimalny rozmiar danych pakietu */
- /* Funkcja obsługująca pakiet. Patrz gg_session_handle_packet(). */
- int (*handler)(struct gg_session *, uint32_t, const char *, size_t, struct gg_event *);
-static int gg_ack_110(struct gg_session *gs, GG110Ack__Type type, uint32_t seq, struct gg_event *ge)
- GG110Ack msg = GG110_ACK__INIT;
- if (!GG_PROTOBUF_SEND(gs, ge, GG_ACK110, gg110_ack, msg))
-static void gg_sync_time(struct gg_session *gs, time_t server_time)
- time_t local_time = time(NULL);
- int time_diff = server_time - local_time;
- if (gs->private_data->time_diff == time_diff)
- gs->private_data->time_diff = time_diff;
- gg_debug_session(gs, GG_DEBUG_MISC | GG_DEBUG_VERBOSE,
- "// time synchronized (diff = %d)\n", time_diff);
-static int gg_session_handle_welcome_110(struct gg_session *gs, uint32_t seed,
- GG105Login msg = GG105_LOGIN__INIT;
- const char *client_name = GG11_VERSION;
- const char *client_version = GG_DEFAULT_CLIENT_VERSION_110;
- const char *client_target = GG11_TARGET;
- uint8_t dummy4[4] = {0, 0, 0, 0};
- if (gs->hash_type != GG_LOGIN_HASH_SHA1) {
- gg_debug_session(gs, GG_DEBUG_ERROR, "// Unsupported hash type "
- "for this protocol version\n");
- gg_connection_failure(gs, ge, GG_FAILURE_INTERNAL);
- if (gg_login_hash_sha1_2(gs->password, seed, hash) == -1) {
- gg_debug_session(gs, GG_DEBUG_ERROR, "// gg_watch_fd() "
- "gg_login_hash_sha1_2() failed, "
- "probably out of memory\n");
- gg_connection_failure(gs, ge, GG_FAILURE_INTERNAL);
- if (gs->client_version != NULL && !isdigit(gs->client_version[0])) {
- if (gs->client_version != NULL)
- client_version = gs->client_version;
- snprintf(client_str, sizeof(client_str), "%s%s%s",
- client_name, client_version, client_target);
- client_str[sizeof(client_str) - 1] = '\0';
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd() "
- "sending GG_LOGIN105 packet\n");
- gg_protobuf_set_uin(&msg.uin, gs->uin, NULL);
- msg.client = client_str;
- /* flagi gg8 są różne od tych dla gg11 */
- msg.initial_status = gs->initial_status ?
- (gs->initial_status & 0xFF) : GG_STATUS_AVAIL;
- if (gs->initial_descr != NULL) {
- msg.initial_descr = gs->initial_descr;
- msg.supported_features = "avatar,StatusComments,gg_account_sdp,"
- "edisc,bot,fanpage,pubdir,botCaps"; */
- msg.supported_features = "avatar,StatusComments,ggaccount,edisc,"
- "music_shared,bot,fanpage,pubdir,botCaps,gifts,Gift";
- msg.dummy4.len = sizeof(dummy4);
- msg.dummy4.data = dummy4;
- if (!GG_PROTOBUF_SEND(gs, ge, GG_LOGIN105, gg105_login, msg))
- gs->state = GG_STATE_READING_REPLY;
- gs->check = GG_CHECK_READ;
-static int gg_session_handle_login110_ok(struct gg_session *gs, uint32_t type,
- const char *ptr, size_t len, struct gg_event *ge)
- GG110LoginOK *msg = gg110_login_ok__unpack(NULL, len, (uint8_t*)ptr);
- if (!GG_PROTOBUF_VALID(gs, "GG110LoginOK", msg))
- gg_protobuf_expected(gs, "GG110LoginOK.dummy1", msg->dummy1, 1);
- gg_sync_time(gs, msg->server_time);
- gg_debug_session(gs, GG_DEBUG_MISC, "// login110_ok: "
- "uin=%u, dummyhash=%s\n", msg->uin, msg->dummyhash);
- gg110_login_ok__free_unpacked(msg, NULL);
- ge->type = GG_EVENT_CONN_SUCCESS;
- gs->state = GG_STATE_CONNECTED;
- gs->check = GG_CHECK_READ;
- gs->status = (gs->initial_status) ? gs->initial_status : GG_STATUS_AVAIL;
- free(gs->status_descr);
- gs->status_descr = gs->initial_descr;
- free(gs->initial_descr);
- gs->initial_descr = NULL;
- * \internal Obsługuje pakiet GG_WELCOME.
- * Patrz gg_packet_handler_t
-static int gg_session_handle_welcome(struct gg_session *gs, uint32_t type,
- const char *ptr, size_t len, struct gg_event *ge)
- const struct gg_welcome *w;
- struct sockaddr_in sin;
- socklen_t sin_len = sizeof(sin);
- const char *client_name, *version, *descr;
- uint32_t client_name_len, version_len, descr_len;
- if (len < sizeof(struct gg_welcome)) {
- ge->type = GG_EVENT_CONN_FAILED;
- ge->event.failure = GG_FAILURE_INVALID;
- gs->state = GG_STATE_IDLE;
- w = (const struct gg_welcome*) ptr;
- seed = gg_fix32(w->key);
- if (gs->protocol_version >= GG_PROTOCOL_VERSION_110)
- return gg_session_handle_welcome_110(gs, seed, ge);
- memset(hash_buf, 0, sizeof(hash_buf));
- switch (gs->hash_type) {
- case GG_LOGIN_HASH_GG32:
- hash = gg_fix32(gg_login_hash((unsigned char*) gs->password, seed));
- gg_debug_session(gs, GG_DEBUG_DUMP, "// gg_watch_fd() "
- "challenge %.4x --> GG32 hash %.8x\n",
- memcpy(hash_buf, &hash, sizeof(hash));
- case GG_LOGIN_HASH_SHA1:
-#ifndef GG_DEBUG_DISABLE
- if (gg_login_hash_sha1_2(gs->password, seed, hash_buf) == -1) {
- gg_debug_session(gs, GG_DEBUG_MISC,
- "// gg_watch_fd() gg_login_hash_sha1_2()"
- " failed, probably out of memory\n");
- ge->type = GG_EVENT_CONN_FAILED;
- ge->event.failure = GG_FAILURE_INTERNAL;
- gs->state = GG_STATE_IDLE;
-#ifndef GG_DEBUG_DISABLE
- for (i = 0; i < 40; i += 2)
- snprintf(tmp + i, sizeof(tmp) - i, "%02x", hash_buf[i / 2]);
- gg_debug_session(gs, GG_DEBUG_DUMP, "// gg_watch_fd() "
- "challenge %.4x --> SHA1 hash: %s\n",
- if (gs->password != NULL && (gs->flags & (1 << GG_SESSION_FLAG_CLEAR_PASSWORD))) {
- memset(gs->password, 0, strlen(gs->password));
- if (!getsockname(gs->fd, (struct sockaddr*) &sin, &sin_len)) {
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd() "
- "detected address to %s\n", inet_ntoa(sin.sin_addr));
- local_ip = sin.sin_addr.s_addr;
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd() unable to detect address\n");
- if (gs->external_addr == 0)
- gs->external_addr = local_ip;
- memset(&l80, 0, sizeof(l80));
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd() sending GG_LOGIN80 packet\n");
- l80.uin = gg_fix32(gs->uin);
- memcpy(l80.language, GG8_LANG, sizeof(l80.language));
- l80.hash_type = gs->hash_type;
- memcpy(l80.hash, hash_buf, sizeof(l80.hash));
- l80.status = gg_fix32(gs->initial_status ? gs->initial_status : GG_STATUS_AVAIL);
- l80.flags = gg_fix32(gs->status_flags);
- l80.features = gg_fix32(gs->protocol_features);
- l80.image_size = gs->image_size;
- if (gs->client_version != NULL && !isdigit(gs->client_version[0])) {
- client_name = GG8_VERSION;
- client_name_len = strlen(GG8_VERSION);
- version = (gs->client_version != NULL) ? gs->client_version : GG_DEFAULT_CLIENT_VERSION_100;
- version_len = gg_fix32(client_name_len + strlen(version));
- descr = (gs->initial_descr != NULL) ? gs->initial_descr : "";
- descr_len = (gs->initial_descr != NULL) ? gg_fix32(strlen(gs->initial_descr)) : 0;
- ret = gg_send_packet(gs,
- &version_len, sizeof(version_len),
- client_name, client_name_len,
- version, strlen(version),
- &descr_len, sizeof(descr_len),
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd() "
- "sending packet failed. (errno=%d, %s)\n",
- errno, strerror(errno));
- ge->type = GG_EVENT_CONN_FAILED;
- ge->event.failure = GG_FAILURE_WRITING;
- gs->state = GG_STATE_IDLE;
- gs->state = GG_STATE_READING_REPLY;
- gs->check = GG_CHECK_READ;
- * \internal Obsługuje pakiet GG_LOGIN_OK.
- * Patrz gg_packet_handler_t
-static int gg_session_handle_login_ok(struct gg_session *gs, uint32_t type,
- const char *ptr, size_t len, struct gg_event *ge)
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd() login succeded\n");
- ge->type = GG_EVENT_CONN_SUCCESS;
- gs->state = GG_STATE_CONNECTED;
- gs->check = GG_CHECK_READ;
- gs->status = (gs->initial_status) ? gs->initial_status : GG_STATUS_AVAIL;
- free(gs->status_descr);
- gs->status_descr = gs->initial_descr;
- free(gs->initial_descr);
- gs->initial_descr = NULL;
- * \internal Obsługuje pakiet GG_LOGIN_FAILED.
- * Patrz gg_packet_handler_t
-static int gg_session_handle_login_failed(struct gg_session *gs, uint32_t type,
- const char *ptr, size_t len, struct gg_event *ge)
- if (type != GG_DISCONNECTING)
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd() login failed\n");
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd() too many incorrect password attempts\n");
- ge->type = GG_EVENT_CONN_FAILED;
- ge->event.failure = (type != GG_DISCONNECTING) ? GG_FAILURE_PASSWORD : GG_FAILURE_INTRUDER;
- gs->state = GG_STATE_IDLE;
- * \internal Obsługuje pakiet GG_SEND_MSG_ACK.
- * Patrz gg_packet_handler_t
-static int gg_session_handle_send_msg_ack(struct gg_session *gs, uint32_t type,
- const char *ptr, size_t len, struct gg_event *ge)
- struct gg_session_private *p = gs->private_data;
- const struct gg_send_msg_ack *s = (const struct gg_send_msg_ack*) ptr;
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received a message ack\n");
- ge->type = GG_EVENT_ACK;
- ge->event.ack.status = gg_fix32(s->status);
- ge->event.ack.recipient = gg_fix32(s->recipient);
- ge->event.ack.seq = gg_fix32(s->seq);
- if (ge->event.ack.seq == 0 && p->imgout_waiting_ack > 0)
- p->imgout_waiting_ack--;
- * \internal Obsługuje pakiet GG_SEND_MSG_ACK110.
-static int gg_session_handle_send_msg_ack_110(struct gg_session *gs,
- uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
- struct gg_session_private *p = gs->private_data;
- GG110MessageAck *msg = gg110_message_ack__unpack(NULL, len, (uint8_t*)ptr);
- if (!GG_PROTOBUF_VALID(gs, "GG110MessageAck", msg))
- if (msg->dummy1 == 0x4000) {
- /* zaobserwowane w EKG rev2856, po wywołaniu check_conn, czyli
- * gg_image_request(sess, uin, 0, time(NULL));
- gg_debug_session(gs, GG_DEBUG_MISC | GG_DEBUG_WARNING,
- "// gg_session_handle_send_msg_ack_110() magic dummy1 "
- } else if (msg->dummy1 != 0) {
- gg_debug_session(gs, GG_DEBUG_MISC | GG_DEBUG_WARNING,
- "// gg_session_handle_send_msg_ack_110() unknown dummy1 "
- "value: %x\n", msg->dummy1);
- gg_debug_session(gs, GG_DEBUG_VERBOSE,
- "// gg_session_handle_send_msg_ack_110() "
- "%s=%016" PRIx64 " %s=%016" PRIx64 "\n",
- msg->has_msg_id ? "msg_id" : "0", msg->msg_id,
- msg->has_conv_id ? "conv_id" : "0", msg->conv_id);
- for (i = 0; i < msg->n_links; i++) {
- GG110MessageAckLink *link = msg->links[i];
- if (!GG_PROTOBUF_VALID(gs, "GG110MessageAckLink", link))
- gg_debug_session(gs, GG_DEBUG_MISC,
- "// gg_session_handle_send_msg_ack_110() "
- "got link (id=%" PRIx64 ") \"%s\"\n", link->id, link->url);
- ge->type = GG_EVENT_ACK110;
- ge->event.ack110.msg_type = msg->msg_type;
- ge->event.ack110.seq = msg->seq;
- ge->event.ack110.time = msg->time;
- gg_compat_message_ack(gs, msg->seq);
- gg110_message_ack__free_unpacked(msg, NULL);
- if (msg->seq == 0 && p->imgout_waiting_ack > 0)
- p->imgout_waiting_ack--;
- * \internal Obsługuje pakiet GG_PONG.
- * Patrz gg_packet_handler_t
-static int gg_session_handle_pong(struct gg_session *gs, uint32_t type,
- const char *ptr, size_t len, struct gg_event *ge)
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received a pong\n");
- ge->type = GG_EVENT_PONG;
- gs->last_pong = time(NULL);
- * \internal Obsługuje pakiet GG_DISCONNECTING.
- * Patrz gg_packet_handler_t
-static int gg_session_handle_disconnecting(struct gg_session *gs, uint32_t type,
- const char *ptr, size_t len, struct gg_event *ge)
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received disconnection warning\n");
- ge->type = GG_EVENT_DISCONNECT;
- * \internal Obsługuje pakiet GG_DISCONNECT_ACK.
- * Patrz gg_packet_handler_t
-static int gg_session_handle_disconnect_ack(struct gg_session *gs,
- uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received logoff acknowledge\n");
- ge->type = GG_EVENT_DISCONNECT_ACK;
- * \internal Obsługuje pakiety GG_XML_EVENT i GG_XML_ACTION.
- * Patrz gg_packet_handler_t
-static int gg_session_handle_xml_event(struct gg_session *gs, uint32_t type,
- const char *ptr, size_t len, struct gg_event *ge)
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received XML event\n");
- ge->type = GG_EVENT_XML_EVENT;
- ge->event.xml_event.data = malloc(len + 1);
- if (ge->event.xml_event.data == NULL) {
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
- memcpy(ge->event.xml_event.data, ptr, len);
- ge->event.xml_event.data[len] = 0;
-static int gg_session_handle_event_110(struct gg_session *gs, uint32_t type,
- const char *ptr, size_t len, struct gg_event *ge)
- GG110Event *msg = gg110_event__unpack(NULL, len, (uint8_t*)ptr);
- if (!GG_PROTOBUF_VALID(gs, "GG110Event", msg))
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_event_110: "
- "received GG11 event (type=%d, id=%" PRIx64 ")\n", msg->type, msg->id);
- if (msg->type == GG110_EVENT__TYPE__XML) {
- ge->type = GG_EVENT_XML_EVENT;
- ge->event.xml_event.data = strdup(msg->data);
- succ = succ && (ge->event.xml_event.data != NULL);
- } else if (msg->type == GG110_EVENT__TYPE__JSON) {
- ge->type = GG_EVENT_JSON_EVENT;
- ge->event.json_event.data = strdup(msg->data);
- succ = succ && (ge->event.json_event.data != NULL);
- ge->event.json_event.type = strdup(msg->subtype);
- succ = succ && (ge->event.json_event.type != NULL);
- gg_debug_session(gs, GG_DEBUG_WARNING,
- "// gg_session_handle_event_110: "
- "unsupported GG11 event type: %d\n", msg->type);
- if (gg_ack_110(gs, GG110_ACK__TYPE__MPA, msg->seq, ge) != 0) {
- gg110_event__free_unpacked(msg, NULL);
- * \internal Obsługuje pakiet GG_PUBDIR50_REPLY.
- * Patrz gg_packet_handler_t
-static int gg_session_handle_pubdir50_reply(struct gg_session *gs,
- uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received pubdir/search reply\n");
- return gg_pubdir50_handle_reply_sess(gs, ge, ptr, len);
- * \internal Obsługuje pakiet GG_USERLIST_REPLY.
- * Patrz gg_packet_handler_t
-static int gg_session_handle_userlist_reply(struct gg_session *gs,
- uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received userlist reply\n");
- /* jeśli odpowiedź na eksport, wywołaj zdarzenie tylko
- * gdy otrzymano wszystkie odpowiedzi */
- if (reply_type == GG_USERLIST_PUT_REPLY || reply_type == GG_USERLIST_PUT_MORE_REPLY) {
- if (--gs->userlist_blocks)
- reply_type = GG_USERLIST_PUT_REPLY;
- unsigned int reply_len = (gs->userlist_reply != NULL) ? strlen(gs->userlist_reply) : 0;
- gg_debug_session(gs, GG_DEBUG_MISC, "userlist_reply=%p, len=%"
- GG_SIZE_FMT "\n", gs->userlist_reply, len);
- if (reply_len + len > GG_USERLIST_REPLY_MAX_LENGTH) {
- gg_debug_session(gs, GG_DEBUG_MISC,
- "// gg_session_handle_userlist_reply() "
- "too many userlist replies\n");
- tmp = realloc(gs->userlist_reply, reply_len + len);
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
- gs->userlist_reply = tmp;
- memcpy(gs->userlist_reply + reply_len, ptr + 1, len - 1);
- gs->userlist_reply[reply_len + len - 1] = 0;
- if (reply_type == GG_USERLIST_GET_MORE_REPLY)
- ge->type = GG_EVENT_USERLIST;
- ge->event.userlist.type = reply_type;
- ge->event.userlist.reply = gs->userlist_reply;
- gs->userlist_reply = NULL;
- * \internal Obsługuje pakiet GG_DCC7_ID_REPLY.
- * Patrz gg_packet_handler_t
-static int gg_session_handle_dcc7_id_reply(struct gg_session *gs, uint32_t type,
- const char *ptr, size_t len, struct gg_event *ge)
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received dcc7 id packet\n");
- return gg_dcc7_handle_id(gs, ge, ptr, len);
- * \internal Obsługuje pakiet GG_DCC7_ACCEPT.
- * Patrz gg_packet_handler_t
-static int gg_session_handle_dcc7_accept(struct gg_session *gs, uint32_t type,
- const char *ptr, size_t len, struct gg_event *ge)
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received dcc7 accept\n");
- return gg_dcc7_handle_accept(gs, ge, ptr, len);
- * \internal Obsługuje pakiet GG_DCC7_NEW.
- * Patrz gg_packet_handler_t
-static int gg_session_handle_dcc7_new(struct gg_session *gs, uint32_t type,
- const char *ptr, size_t len, struct gg_event *ge)
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received dcc7 request\n");
- return gg_dcc7_handle_new(gs, ge, ptr, len);
- * \internal Obsługuje pakiet GG_DCC7_REJECT.
- * Patrz gg_packet_handler_t
-static int gg_session_handle_dcc7_reject(struct gg_session *gs, uint32_t type,
- const char *ptr, size_t len, struct gg_event *ge)
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received dcc7 reject\n");
- return gg_dcc7_handle_reject(gs, ge, ptr, len);
- * \internal Obsługuje pakiet GG_DCC7_INFO.
- * Patrz gg_packet_handler_t
-static int gg_session_handle_dcc7_info(struct gg_session *gs, uint32_t type,
- const char *ptr, size_t len, struct gg_event *ge)
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received dcc7 info\n");
- return gg_dcc7_handle_info(gs, ge, ptr, len);
- * \internal Analizuje przychodzący pakiet z obrazkiem.
- * \param e Struktura zdarzenia
- * \param p Bufor z danymi
- * \param len Długość bufora
- * \param sess Struktura sesji
- * \param sender Numer nadawcy
- * \param type Typ pakietu (NIE typ GG_MSG_OPTION_IMAGE_*)
-static void gg_image_queue_parse(struct gg_event *e, const char *p,
- unsigned int len, struct gg_session *sess, uin_t sender,
- const struct gg_msg_image_reply *i = (const void*) p;
- struct gg_image_queue *q, *qq;
- gg_debug_session(sess, GG_DEBUG_VERBOSE,
- "// gg_image_queue_parse(%p, %p, %d, %p, %u, %d)\n",
- e, p, len, sess, sender, type);
- if (!p || !sess || !e) {
- if (i->flag == GG_MSG_OPTION_IMAGE_REQUEST) {
- e->type = GG_EVENT_IMAGE_REQUEST;
- e->event.image_request.sender = sender;
- e->event.image_reply.size = i->size;
- e->event.image_request.crc32 = i->crc32;
- /* znajdź dany obrazek w kolejce danej sesji */
- for (qq = sess->images, q = NULL; qq; qq = qq->next) {
- if (sender == qq->sender && i->size == qq->size && i->crc32 == qq->crc32) {
- gg_debug_session(sess, GG_DEBUG_WARNING,
- "// gg_image_queue_parse() unknown image from %d, "
- "size=%d, crc32=%.8x\n", sender, i->size, i->crc32);
- if (q->packet_type == 0)
- if (q->packet_type != type)
- if (i->flag == GG_MSG_OPTION_IMAGE_REPLY) {
- len -= sizeof(struct gg_msg_image_reply);
- p += sizeof(struct gg_msg_image_reply);
- if (memchr(p, 0, len) == NULL) {
- gg_debug_session(sess, GG_DEBUG_ERROR,
- "// gg_image_queue_parse() malformed packet "
- "from %d, unlimited filename\n", sender);
- if (!(q->filename = strdup(p))) {
- gg_debug_session(sess, GG_DEBUG_ERROR, "// gg_image_queue_parse() out of memory\n");
- } else if (i->flag == GG_MSG_OPTION_IMAGE_REPLY_MORE) {
- len -= sizeof(struct gg_msg_image_reply);
- p += sizeof(struct gg_msg_image_reply);
- gg_debug_session(sess, GG_DEBUG_WARNING, "// gg_image_queue_parse() unexpected flag\n");
- if (q->done + len > q->size) {
- gg_debug_session(sess, GG_DEBUG_ERROR, "// gg_image_queue_parse() got too much\n");
- len = q->size - q->done;
- memcpy(q->image + q->done, p, len);
- gg_debug_session(sess, GG_DEBUG_VERBOSE,
- "// gg_image_queue_parse() got image part (done: %d of %d)\n",
- /* jeśli skończono odbierać obrazek, wygeneruj zdarzenie */
- if (q->done >= q->size) {
- gg_debug_session(sess, GG_DEBUG_VERBOSE,
- "// gg_image_queue_parse() image ready\n");
- e->type = GG_EVENT_IMAGE_REPLY;
- e->event.image_reply.sender = sender;
- e->event.image_reply.size = q->size;
- e->event.image_reply.crc32 = q->crc32;
- e->event.image_reply.filename = q->filename;
- e->event.image_reply.image = q->image;
- gg_image_queue_remove(sess, q, 0);
- * \internal Analizuje informacje rozszerzone wiadomości.
- * \param sess Struktura sesji.
- * \param e Struktura zdarzenia.
- * \param sender Numer nadawcy.
- * \param p Wskaźnik na dane rozszerzone.
- * \param packet_end Wskaźnik na koniec pakietu.
- * \param packet_type Typ pakietu, w którym otrzymaliśmy wiadomość.
- * \return 0 jeśli się powiodło, -1 jeśli wiadomość obsłużono i wynik ma
- * zostać przekazany aplikacji, -2 jeśli wystąpił błąd ogólny, -3 jeśli
- * wiadomość jest niepoprawna.
-static int gg_handle_recv_msg_options(struct gg_session *sess,
- struct gg_event *e, uin_t sender, const char *p, const char *packet_end,
- while (p < packet_end) {
- case GG_MSG_OPTION_CONFERENCE:
- const struct gg_msg_recipients *m = (const void*) p;
- gg_debug_session(sess, GG_DEBUG_MISC,
- "// gg_handle_recv_msg_options()"
- " packet out of bounds (1)\n");
- count = gg_fix32(m->count);
- if (p + count * sizeof(uin_t) > packet_end ||
- p + count * sizeof(uin_t) < p ||
- gg_debug_session(sess, GG_DEBUG_MISC,
- "// gg_handle_recv_msg_options()"
- " packet out of bounds (1.5)\n");
- if (e->event.msg.recipients != NULL) {
- gg_debug_session(sess, GG_DEBUG_MISC,
- "// gg_handle_recv_msg_options()"
- " e->event.msg.recipients already exist\n");
- e->event.msg.recipients = malloc(count * sizeof(uin_t));
- if (e->event.msg.recipients == NULL) {
- gg_debug_session(sess, GG_DEBUG_MISC,
- "// gg_handle_recv_msg_options()"
- " not enough memory for recipients data\n");
- memcpy(e->event.msg.recipients, p, count * sizeof(uin_t));
- p += count * sizeof(uin_t);
- for (i = 0; i < count; i++)
- e->event.msg.recipients[i] = gg_fix32(e->event.msg.recipients[i]);
- e->event.msg.recipients_count = count;
- case GG_MSG_OPTION_ATTRIBUTES:
- if (p + 3 > packet_end) {
- gg_debug_session(sess, GG_DEBUG_MISC,
- "// gg_handle_recv_msg_options()"
- " packet out of bounds (2)\n");
- memcpy(&len, p + 1, sizeof(uint16_t));
- if (e->event.msg.formats != NULL) {
- gg_debug_session(sess, GG_DEBUG_MISC,
- "// gg_handle_recv_msg_options()"
- " e->event.msg.formats already exist\n");
- gg_debug_session(sess, GG_DEBUG_MISC,
- "// gg_handle_recv_msg_options()"
- " not enough memory for richtext data\n");
- if (p + len > packet_end) {
- gg_debug_session(sess, GG_DEBUG_MISC,
- "// gg_handle_recv_msg_options()"
- " packet out of bounds (3)\n");
- e->event.msg.formats = buf;
- e->event.msg.formats_length = len;
- case GG_MSG_OPTION_IMAGE_REQUEST:
- const struct gg_msg_image_request *i = (const void*) p;
- if (p + sizeof(*i) > packet_end) {
- gg_debug_session(sess, GG_DEBUG_MISC,
- "// gg_handle_recv_msg() "
- "packet out of bounds (3)\n");
- if (e->event.msg.formats != NULL || e->event.msg.recipients != NULL) {
- gg_debug_session(sess, GG_DEBUG_MISC,
- "// gg_handle_recv_msg_options()"
- " mixed options (1)\n");
- e->event.image_request.sender = sender;
- e->event.image_request.size = gg_fix32(i->size);
- e->event.image_request.crc32 = gg_fix32(i->crc32);
- e->type = GG_EVENT_IMAGE_REQUEST;
- case GG_MSG_OPTION_IMAGE_REPLY:
- case GG_MSG_OPTION_IMAGE_REPLY_MORE:
- struct gg_msg_image_reply *rep = (void*) p;
- if (e->event.msg.formats != NULL || e->event.msg.recipients != NULL) {
- gg_debug_session(sess, GG_DEBUG_MISC,
- "// gg_handle_recv_msg_options() "
- "mixed options (2)\n");
- if (p + sizeof(struct gg_msg_image_reply) == packet_end) {
- /* pusta odpowiedź - klient po drugiej stronie nie ma żądanego obrazka */
- e->type = GG_EVENT_IMAGE_REPLY;
- e->event.image_reply.sender = sender;
- e->event.image_reply.size = 0;
- e->event.image_reply.crc32 = gg_fix32(rep->crc32);
- e->event.image_reply.filename = NULL;
- e->event.image_reply.image = NULL;
- } else if (p + sizeof(struct gg_msg_image_reply) + 1 > packet_end) {
- gg_debug_session(sess, GG_DEBUG_MISC,
- "// gg_handle_recv_msg() "
- "packet out of bounds (4)\n");
- rep->size = gg_fix32(rep->size);
- rep->crc32 = gg_fix32(rep->crc32);
- gg_image_queue_parse(e, p, (unsigned int)(packet_end - p), sess, sender, packet_type);
- gg_debug_session(sess, GG_DEBUG_MISC,
- "// gg_handle_recv_msg() "
- "unknown payload 0x%.2x\n", *p);
- * \internal Wysyła potwierdzenie odebrania wiadomości.
- * \param gs Struktura sesji
- * \param seq Numer sekwencyjny odebranej wiadomości
- * \return 0 jeśli się powiodło, -1 jeśli wystąpił błąd
-static int gg_session_send_msg_ack(struct gg_session *gs, uint32_t seq)
- struct gg_recv_msg_ack pkt;
- gg_debug_session(gs, GG_DEBUG_FUNCTION, "** gg_session_send_msg_ack(%p);\n", gs);
- if ((gs->protocol_features & GG_FEATURE_MSG_ACK) == 0)
- /* Kiedyś zdawało nam się, że mamy wysyłać liczbę odebranych
- * wiadomości, ale okazało się, że numer sekwencyjny. */
- pkt.seq = gg_fix32(seq);
- return gg_send_packet(gs, GG_RECV_MSG_ACK, &pkt, sizeof(pkt), NULL);
- * \internal Obsługuje pakiet GG_RECV_MSG.
- * Patrz gg_packet_handler_t
-static int gg_session_handle_recv_msg(struct gg_session *sess, uint32_t type,
- const char *packet, size_t length, struct gg_event *e)
- const struct gg_recv_msg *r = (const struct gg_recv_msg*) packet;
- const char *payload = packet + sizeof(struct gg_recv_msg);
- const char *payload_end = packet + length;
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_handle_recv_msg(%p, %"
- GG_SIZE_FMT ", %p);\n", packet, length, e);
- if ((r->seq == 0) && (r->msgclass == 0)) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg() oops, silently ignoring the bait\n");
- /* jednobajtowa wiadomość o treści \x02 to żądanie połączenia DCC */
- if (*payload == GG_MSG_CALLBACK && payload == payload_end - 1) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg() received ctcp packet\n");
- options = memchr(payload, 0, (size_t) (payload_end - payload));
- gg_debug_session(sess, GG_DEBUG_MISC,
- "// gg_handle_recv_msg() malformed packet, "
- "message out of bounds (0)\n");
- length = (size_t) (options - payload);
- switch (gg_handle_recv_msg_options(sess, e, gg_fix32(r->sender), options + 1, payload_end, type)) {
- gg_session_send_msg_ack(sess, gg_fix32(r->seq));
- case -3: /* malformed */
- e->type = GG_EVENT_MSG;
- e->event.msg.msgclass = gg_fix32(r->msgclass);
- e->event.msg.sender = gg_fix32(r->sender);
- e->event.msg.time = gg_fix32(r->time);
- e->event.msg.seq = gg_fix32(r->seq);
- e->event.msg.message = (unsigned char*)gg_encoding_convert(payload,
- GG_ENCODING_CP1250, sess->encoding, length, -1);
- if (e->event.msg.message == NULL) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_session_handle_recv_msg() out of memory\n");
- len = gg_message_text_to_html(NULL, (char*)e->event.msg.message,
- sess->encoding, e->event.msg.formats,
- e->event.msg.formats_length);
- e->event.msg.xhtml_message = malloc(len + 1);
- if (e->event.msg.xhtml_message == NULL) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_session_handle_recv_msg() out of memory\n");
- gg_message_text_to_html(e->event.msg.xhtml_message,
- (char*)e->event.msg.message, sess->encoding,
- e->event.msg.formats, e->event.msg.formats_length);
- gg_session_send_msg_ack(sess, gg_fix32(r->seq));
- free(e->event.msg.message);
- free(e->event.msg.xhtml_message);
- free(e->event.msg.recipients);
- free(e->event.msg.formats);
- e->type = GG_EVENT_NONE;
- free(e->event.msg.message);
- free(e->event.msg.xhtml_message);
- free(e->event.msg.recipients);
- free(e->event.msg.formats);
- gg_session_send_msg_ack(sess, gg_fix32(r->seq));
- * \internal Obsługuje pakiet GG_RECV_MSG80.
- * Patrz gg_packet_handler_t
-static int gg_session_handle_recv_msg_80(struct gg_session *sess, uint32_t type,
- const char *packet, size_t length, struct gg_event *e)
- const struct gg_recv_msg80 *r = (const struct gg_recv_msg80*) packet;
- gg_debug_session(sess, GG_DEBUG_FUNCTION,
- "** gg_handle_recv_msg80(%p, %" GG_SIZE_FMT ", %p);\n",
- if (r->seq == 0 && r->msgclass == 0) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg80() oops, silently ignoring the bait\n");
- offset_plain = gg_fix32(r->offset_plain);
- offset_attr = gg_fix32(r->offset_attr);
- if (offset_plain < sizeof(struct gg_recv_msg80) || offset_plain >= length) {
- gg_debug_session(sess, GG_DEBUG_MISC,
- "// gg_handle_recv_msg80() malformed packet, "
- "message out of bounds (0)\n");
- if (offset_attr < sizeof(struct gg_recv_msg80) || offset_attr > length) {
- gg_debug_session(sess, GG_DEBUG_MISC,
- "// gg_handle_recv_msg80() malformed packet, "
- "attr out of bounds (1)\n");
- offset_attr = 0; /* nie parsuj attr. */
- /* Normalna sytuacja, więc nie podpada pod powyższy warunek. */
- if (offset_attr == length)
- if (memchr(packet + offset_plain, 0, length - offset_plain) == NULL) {
- gg_debug_session(sess, GG_DEBUG_MISC,
- "// gg_handle_recv_msg80() malformed packet, "
- "message out of bounds (2)\n");
- if (offset_plain > sizeof(struct gg_recv_msg80) && memchr(packet +
- sizeof(struct gg_recv_msg80), 0, offset_plain -
- sizeof(struct gg_recv_msg80)) == NULL)
- gg_debug_session(sess, GG_DEBUG_MISC,
- "// gg_handle_recv_msg80() malformed packet, "
- "message out of bounds (3)\n");
- e->type = (type != GG_RECV_OWN_MSG) ? GG_EVENT_MSG : GG_EVENT_MULTILOGON_MSG;
- e->event.msg.msgclass = gg_fix32(r->msgclass);
- e->event.msg.sender = gg_fix32(r->sender);
- e->event.msg.time = gg_fix32(r->time);
- e->event.msg.seq = gg_fix32(r->seq);
- if (offset_attr != 0) {
- switch (gg_handle_recv_msg_options(sess, e, gg_fix32(r->sender),
- packet + offset_attr, packet + length, type))
- gg_session_send_msg_ack(sess, gg_fix32(r->seq));
- case -3: /* malformed */
- if (sess->encoding == GG_ENCODING_CP1250) {
- e->event.msg.message = (unsigned char*) strdup(packet + offset_plain);
- if (e->event.msg.message == NULL) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_session_handle_recv_msg_80() out of memory\n");
- if (offset_plain > sizeof(struct gg_recv_msg80)) {
- len = gg_message_html_to_text(NULL, NULL, &fmt_len,
- packet + sizeof(struct gg_recv_msg80),
- e->event.msg.message = malloc(len + 1);
- if (e->event.msg.message == NULL) {
- gg_debug_session(sess, GG_DEBUG_MISC,
- "// gg_session_handle_recv_msg_80() "
- free(e->event.msg.formats);
- e->event.msg.formats_length = fmt_len;
- e->event.msg.formats = malloc(fmt_len);
- if (e->event.msg.formats == NULL) {
- gg_debug_session(sess, GG_DEBUG_MISC,
- "// gg_session_handle_recv_msg_80() "
- gg_message_html_to_text((char*)e->event.msg.message,
- e->event.msg.formats, NULL,
- packet + sizeof(struct gg_recv_msg80),
- e->event.msg.message = (unsigned char*)gg_encoding_convert(
- packet + offset_plain, GG_ENCODING_CP1250,
- sess->encoding, -1, -1);
- if (e->event.msg.message == NULL) {
- gg_debug_session(sess, GG_DEBUG_MISC,
- "// gg_session_handle_recv_msg_80() "
- if (offset_plain > sizeof(struct gg_recv_msg80)) {
- e->event.msg.xhtml_message = gg_encoding_convert(
- packet + sizeof(struct gg_recv_msg80), GG_ENCODING_UTF8,
- sess->encoding, -1, -1);
- if (e->event.msg.xhtml_message == NULL) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_session_handle_recv_msg_80() out of memory\n");
- len = gg_message_text_to_html(NULL,
- (char*)e->event.msg.message, sess->encoding,
- e->event.msg.formats, e->event.msg.formats_length);
- e->event.msg.xhtml_message = malloc(len + 1);
- if (e->event.msg.xhtml_message == NULL) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_session_handle_recv_msg_80() out of memory\n");
- gg_message_text_to_html(e->event.msg.xhtml_message,
- (char*)e->event.msg.message, sess->encoding,
- e->event.msg.formats, e->event.msg.formats_length);
- gg_session_send_msg_ack(sess, gg_fix32(r->seq));
- free(e->event.msg.message);
- free(e->event.msg.xhtml_message);
- free(e->event.msg.recipients);
- free(e->event.msg.formats);
- e->type = GG_EVENT_NONE;
- free(e->event.msg.message);
- free(e->event.msg.xhtml_message);
- free(e->event.msg.recipients);
- free(e->event.msg.formats);
- gg_session_send_msg_ack(sess, gg_fix32(r->seq));
-static int gg_session_handle_recv_msg_110(struct gg_session *gs, uint32_t type,
- const char *ptr, size_t len, struct gg_event *ge)
- GG110RecvMessage *msg = gg110_recv_message__unpack(NULL, len, (uint8_t*)ptr);
- struct gg_event_msg *ev = &ge->event.msg;
- gg_debug_session(gs, GG_DEBUG_FUNCTION,
- "** gg_session_handle_recv_msg_110(%p, %" GG_SIZE_FMT
- ", %p);\n", ptr, len, ge);
- if (!GG_PROTOBUF_VALID(gs, "GG110RecvMessage", msg))
- if (type == GG_CHAT_RECV_MSG || type == GG_CHAT_RECV_OWN_MSG)
- ack_type = GG110_ACK__TYPE__CHAT;
- ack_type = GG110_ACK__TYPE__MSG;
- if (msg->has_msg_id || msg->has_conv_id) {
- msg->msg_id = msg->has_msg_id ? msg->msg_id : 0;
- msg->conv_id = msg->has_conv_id ? msg->conv_id : 0;
- gg_debug_session(gs, GG_DEBUG_VERBOSE,
- "// gg_session_handle_recv_msg_110() "
- "msg_id=%016" PRIx64 " conv_id=%016" PRIx64 "\n",
- msg->msg_id, msg->conv_id);
- sender = gg_protobuf_get_uin(msg->sender);
- else if (type == GG_CHAT_RECV_OWN_MSG)
- if (msg->has_data && msg->msg_plain[0] == '\0') {
- if (msg->data.len < sizeof(struct gg_msg_image_reply)) {
- gg_debug_session(gs, GG_DEBUG_ERROR,
- "// gg_session_handle_recv_msg_110() "
- "packet too small (%" GG_SIZE_FMT " < %"
- GG_SIZE_FMT ")\n", msg->data.len,
- sizeof(struct gg_msg_image_reply));
- gg_image_queue_parse(ge, (char *)msg->data.data,
- msg->data.len, gs, sender, type);
- gg110_recv_message__free_unpacked(msg, NULL);
- return gg_ack_110(gs, GG110_ACK__TYPE__MSG, seq, ge);
- if (type == GG_RECV_OWN_MSG110 || type == GG_CHAT_RECV_OWN_MSG)
- ge->type = GG_EVENT_MULTILOGON_MSG;
- ge->type = GG_EVENT_MSG;
- ev->msgclass = GG_CLASS_CHAT;
- ev->flags = msg->flags;
- if (abs(msg->time - gg_server_time(gs)) > 2)
- ev->msgclass |= GG_CLASS_QUEUED;
- if (msg->msg_plain[0] != '\0') {
- ev->message = (unsigned char*)gg_encoding_convert(
- msg->msg_plain, GG_ENCODING_UTF8, gs->encoding, -1, -1);
- succ = succ && (ev->message != NULL);
- ev->xhtml_message = NULL;
- if (msg->msg_xhtml != NULL) {
- ev->xhtml_message = gg_encoding_convert(
- msg->msg_xhtml, GG_ENCODING_UTF8, gs->encoding, -1, -1);
- succ = succ && (ev->xhtml_message != NULL);
- /* wiadomości wysłane z mobilnego gg nie posiadają wersji xhtml */
- if (ev->message == NULL && ev->xhtml_message == NULL) {
- ev->message = (unsigned char*)strdup("");
- succ = succ && (ev->message != NULL);
- } else if (ev->message == NULL) {
- ev->message = (unsigned char*)gg_message_html_to_text_110(
- succ = succ && (ev->message != NULL);
- } else if (ev->xhtml_message == NULL) {
- ev->xhtml_message = gg_message_text_to_html_110(
- (char*)ev->message, -1);
- succ = succ && (ev->xhtml_message != NULL);
- /* otrzymywane tylko od gg <= 10.5 */
- ev->formats_length = 0;
- if (msg->has_data && succ) {
- ev->formats_length = msg->data.len;
- ev->formats = malloc(msg->data.len);
- if (ev->formats == NULL)
- memcpy(ev->formats, msg->data.data, msg->data.len);
- if (msg->has_chat_id && succ) {
- ev->chat_id = msg->chat_id;
- chat = gg_chat_find(gs, msg->chat_id);
- size_t rcpt_size = chat->participants_count *
- ev->recipients = malloc(rcpt_size);
- ev->recipients_count = chat->participants_count;
- if (ev->recipients == NULL)
- memcpy(ev->recipients, chat->participants,
- gg110_recv_message__free_unpacked(msg, NULL);
- if (gg_ack_110(gs, ack_type, seq, ge) != 0)
- free(ev->xhtml_message);
- * \internal Obsługuje pakiet GG_STATUS.
- * Patrz gg_packet_handler_t
-static int gg_session_handle_status(struct gg_session *gs, uint32_t type,
- const char *ptr, size_t len, struct gg_event *ge)
- const struct gg_status *s = (const void*) ptr;
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received a status change\n");
- ge->type = GG_EVENT_STATUS;
- ge->event.status.uin = gg_fix32(s->uin);
- ge->event.status.status = gg_fix32(s->status);
- ge->event.status.descr = NULL;
- if (len > sizeof(*s)) {
- ge->event.status.descr = gg_encoding_convert(ptr + sizeof(*s),
- GG_ENCODING_CP1250, gs->encoding, len - sizeof(*s), -1);
- if (ge->event.status.descr == NULL) {
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
- * \internal Obsługuje pakiety GG_STATUS60, GG_STATUS77 i GG_STATUS80BETA.
- * Patrz gg_packet_handler_t
-static int gg_session_handle_status_60_77_80beta(struct gg_session *gs,
- uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
- const struct gg_status60 *s60 = (const void*) ptr;
- const struct gg_status77 *s77 = (const void*) ptr;
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received a status change\n");
- ge->type = GG_EVENT_STATUS60;
- ge->event.status60.descr = NULL;
- ge->event.status60.time = 0;
- if (type == GG_STATUS60) {
- uin = gg_fix32(s60->uin);
- ge->event.status60.status = s60->status;
- ge->event.status60.remote_ip = s60->remote_ip;
- ge->event.status60.remote_port = gg_fix16(s60->remote_port);
- ge->event.status60.version = s60->version;
- ge->event.status60.image_size = s60->image_size;
- struct_len = sizeof(*s60);
- uin = gg_fix32(s77->uin);
- ge->event.status60.status = s77->status;
- ge->event.status60.remote_ip = s77->remote_ip;
- ge->event.status60.remote_port = gg_fix16(s77->remote_port);
- ge->event.status60.version = s77->version;
- ge->event.status60.image_size = s77->image_size;
- struct_len = sizeof(*s77);
- ge->event.status60.uin = uin & 0x00ffffff;
- ge->event.status60.version |= GG_HAS_AUDIO_MASK;
- ge->event.status60.version |= GG_HAS_AUDIO7_MASK;
- ge->event.status60.version |= GG_ERA_OMNIX_MASK;
- if (len > struct_len) {
- descr_len = len - struct_len;
- ge->event.status60.descr = gg_encoding_convert(ptr + struct_len,
- (type == GG_STATUS80BETA) ? GG_ENCODING_UTF8 : GG_ENCODING_CP1250,
- gs->encoding, descr_len, -1);
- if (ge->event.status60.descr == NULL) {
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
- if (descr_len > 4 && ptr[len - 5] == 0) {
- memcpy(&t, ptr + len - 4, sizeof(uint32_t));
- ge->event.status60.time = gg_fix32(t);
- * \internal Obsługuje pakiet GG_NOTIFY_REPLY.
- * Patrz gg_packet_handler_t
-static int gg_session_handle_notify_reply(struct gg_session *gs, uint32_t type,
- const char *ptr, size_t len, struct gg_event *ge)
- const struct gg_notify_reply *n = (const void*) ptr;
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received a notify reply\n");
- if (gg_fix32(n->status) == GG_STATUS_BUSY_DESCR ||
- gg_fix32(n->status) == GG_STATUS_NOT_AVAIL_DESCR ||
- gg_fix32(n->status) == GG_STATUS_AVAIL_DESCR)
- ge->type = GG_EVENT_NOTIFY_DESCR;
- if (!(ge->event.notify_descr.notify = (void*) malloc(sizeof(*n) * 2))) {
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
- ge->event.notify_descr.notify[1].uin = 0;
- memcpy(ge->event.notify_descr.notify, ptr, sizeof(*n));
- ge->event.notify_descr.notify[0].uin = gg_fix32(ge->event.notify_descr.notify[0].uin);
- ge->event.notify_descr.notify[0].status = gg_fix32(ge->event.notify_descr.notify[0].status);
- ge->event.notify_descr.notify[0].remote_port = gg_fix16(ge->event.notify_descr.notify[0].remote_port);
- ge->event.notify_descr.notify[0].version = gg_fix32(ge->event.notify_descr.notify[0].version);
- descr_len = len - sizeof(*n);
- descr = gg_encoding_convert(ptr + sizeof(*n), GG_ENCODING_CP1250, gs->encoding, descr_len, -1);
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
- ge->event.notify_descr.descr = descr;
- ge->type = GG_EVENT_NOTIFY;
- if (!(ge->event.notify = (void*) malloc(len + 2 * sizeof(*n)))) {
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
- memcpy(ge->event.notify, ptr, len);
- count = len / sizeof(*n);
- ge->event.notify[count].uin = 0;
- for (i = 0; i < count; i++) {
- ge->event.notify[i].uin = gg_fix32(ge->event.notify[i].uin);
- ge->event.notify[i].status = gg_fix32(ge->event.notify[i].status);
- ge->event.notify[i].remote_port = gg_fix16(ge->event.notify[i].remote_port);
- ge->event.notify[i].version = gg_fix32(ge->event.notify[i].version);
- * \internal Obsługuje pakiet GG_STATUS80.
- * Patrz gg_packet_handler_t
-static int gg_session_handle_status_80(struct gg_session *gs, uint32_t type,
- const char *ptr, size_t len, struct gg_event *ge)
- const struct gg_notify_reply80 *n = (const void*) ptr;
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received a status change\n");
- ge->type = GG_EVENT_STATUS60;
- ge->event.status60.uin = gg_fix32(n->uin);
- ge->event.status60.status = gg_fix32(n->status);
- ge->event.status60.remote_ip = n->remote_ip;
- ge->event.status60.remote_port = gg_fix16(n->remote_port);
- ge->event.status60.version = 0;
- ge->event.status60.image_size = n->image_size;
- ge->event.status60.descr = NULL;
- ge->event.status60.time = 0;
- descr_len = gg_fix32(n->descr_len);
- if (descr_len != 0 && sizeof(struct gg_notify_reply80) + descr_len <= len) {
- ge->event.status60.descr = gg_encoding_convert(
- (const char*) n + sizeof(struct gg_notify_reply80),
- GG_ENCODING_UTF8, gs->encoding, descr_len, -1);
- if (ge->event.status60.descr == NULL) {
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
- * \internal Obsługuje pakiet GG_NOTIFY_REPLY80.
- * Patrz gg_packet_handler_t
-static int gg_session_handle_notify_reply_80(struct gg_session *gs,
- uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
- const struct gg_notify_reply80 *n = (const void*) ptr;
- unsigned int length = len, i = 0;
- /* TODO: najpierw przeanalizować strukturę i określić
- * liczbę rekordów, żeby obyć się bez realloc()
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received a notify reply\n");
- ge->type = GG_EVENT_NOTIFY60;
- ge->event.notify60 = malloc(sizeof(*ge->event.notify60));
- if (!ge->event.notify60) {
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
- ge->event.notify60[0].uin = 0;
- while (length >= sizeof(struct gg_notify_reply80)) {
- uin_t uin = gg_fix32(n->uin);
- ge->event.notify60[i].uin = uin;
- ge->event.notify60[i].status = gg_fix32(n->status);
- ge->event.notify60[i].remote_ip = n->remote_ip;
- ge->event.notify60[i].remote_port = gg_fix16(n->remote_port);
- ge->event.notify60[i].version = 0;
- ge->event.notify60[i].image_size = n->image_size;
- ge->event.notify60[i].descr = NULL;
- ge->event.notify60[i].time = 0;
- descr_len = gg_fix32(n->descr_len);
- if (sizeof(struct gg_notify_reply80) + descr_len <= length) {
- ge->event.notify60[i].descr = gg_encoding_convert(
- (const char*) n + sizeof(struct gg_notify_reply80),
- GG_ENCODING_UTF8, gs->encoding, descr_len, -1);
- if (ge->event.notify60[i].descr == NULL) {
- gg_debug_session(gs, GG_DEBUG_MISC,
- "// gg_watch_fd_connected() "
- length -= sizeof(struct gg_notify_reply80) + descr_len;
- n = (const void*) ((const char*) n + sizeof(struct gg_notify_reply80) + descr_len);
- length -= sizeof(struct gg_notify_reply80);
- n = (const void*) ((const char*) n + sizeof(struct gg_notify_reply80));
- if (!(tmp = realloc(ge->event.notify60, (i + 2) * sizeof(*ge->event.notify60)))) {
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
- free(ge->event.notify60);
- ge->event.notify60 = tmp;
- ge->event.notify60[++i].uin = 0;
- * \internal Obsługuje pakiety GG_NOTIFY_REPLY77 i GG_NOTIFY_REPLY80BETA.
- * Patrz gg_packet_handler_t
-static int gg_session_handle_notify_reply_77_80beta(struct gg_session *gs,
- uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
- const struct gg_notify_reply77 *n = (const void*) ptr;
- unsigned int length = len, i = 0;
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received a notify reply\n");
- ge->type = GG_EVENT_NOTIFY60;
- ge->event.notify60 = malloc(sizeof(*ge->event.notify60));
- if (ge->event.notify60 == NULL) {
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
- ge->event.notify60[0].uin = 0;
- while (length >= sizeof(struct gg_notify_reply77)) {
- uin_t uin = gg_fix32(n->uin);
- ge->event.notify60[i].uin = uin & 0x00ffffff;
- ge->event.notify60[i].status = n->status;
- ge->event.notify60[i].remote_ip = n->remote_ip;
- ge->event.notify60[i].remote_port = gg_fix16(n->remote_port);
- ge->event.notify60[i].version = n->version;
- ge->event.notify60[i].image_size = n->image_size;
- ge->event.notify60[i].descr = NULL;
- ge->event.notify60[i].time = 0;
- ge->event.notify60[i].version |= GG_HAS_AUDIO_MASK;
- ge->event.notify60[i].version |= GG_HAS_AUDIO7_MASK;
- ge->event.notify60[i].version |= GG_ERA_OMNIX_MASK;
- if (GG_S_D(n->status)) {
- unsigned char descr_len = *((const char*) n + sizeof(struct gg_notify_reply77));
- if (sizeof(struct gg_notify_reply77) + descr_len <= length) {
- ge->event.notify60[i].descr = gg_encoding_convert(
- (const char*) n + sizeof(struct gg_notify_reply77) + 1,
- (type == GG_NOTIFY_REPLY80BETA) ? GG_ENCODING_UTF8 : GG_ENCODING_CP1250,
- gs->encoding, descr_len, -1);
- if (ge->event.notify60[i].descr == NULL) {
- gg_debug_session(gs, GG_DEBUG_MISC,
- "// gg_watch_fd_connected() "
- length -= sizeof(struct gg_notify_reply77) + descr_len + 1;
- n = (const void*) ((const char*) n + sizeof(struct gg_notify_reply77) + descr_len + 1);
- length -= sizeof(struct gg_notify_reply77);
- n = (const void*) ((const char*) n + sizeof(struct gg_notify_reply77));
- if (!(tmp = realloc(ge->event.notify60, (i + 2) * sizeof(*ge->event.notify60)))) {
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
- free(ge->event.notify60);
- ge->event.notify60 = tmp;
- ge->event.notify60[++i].uin = 0;
- * \internal Obsługuje pakiet GG_NOTIFY_REPLY60.
- * Patrz gg_packet_handler_t
-static int gg_session_handle_notify_reply_60(struct gg_session *gs,
- uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
- const struct gg_notify_reply60 *n = (const void*) ptr;
- unsigned int length = len, i = 0;
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received a notify reply\n");
- ge->type = GG_EVENT_NOTIFY60;
- ge->event.notify60 = malloc(sizeof(*ge->event.notify60));
- if (ge->event.notify60 == NULL) {
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
- ge->event.notify60[0].uin = 0;
- while (length >= sizeof(struct gg_notify_reply60)) {
- uin_t uin = gg_fix32(n->uin);
- ge->event.notify60[i].uin = uin & 0x00ffffff;
- ge->event.notify60[i].status = n->status;
- ge->event.notify60[i].remote_ip = n->remote_ip;
- ge->event.notify60[i].remote_port = gg_fix16(n->remote_port);
- ge->event.notify60[i].version = n->version;
- ge->event.notify60[i].image_size = n->image_size;
- ge->event.notify60[i].descr = NULL;
- ge->event.notify60[i].time = 0;
- ge->event.notify60[i].version |= GG_HAS_AUDIO_MASK;
- ge->event.notify60[i].version |= GG_ERA_OMNIX_MASK;
- if (GG_S_D(n->status)) {
- unsigned char descr_len = *((const char*) n + sizeof(struct gg_notify_reply60));
- if (sizeof(struct gg_notify_reply60) + descr_len <= length) {
- descr = gg_encoding_convert((const char*) n +
- sizeof(struct gg_notify_reply60) + 1,
- GG_ENCODING_CP1250, gs->encoding,
- gg_debug_session(gs, GG_DEBUG_MISC,
- "// gg_watch_fd_connected() "
- ge->event.notify60[i].descr = descr;
- length -= sizeof(struct gg_notify_reply60) + descr_len + 1;
- n = (const void*) ((const char*) n + sizeof(struct gg_notify_reply60) + descr_len + 1);
- length -= sizeof(struct gg_notify_reply60);
- n = (const void*) ((const char*) n + sizeof(struct gg_notify_reply60));
- if (!(tmp = realloc(ge->event.notify60, (i + 2) * sizeof(*ge->event.notify60)))) {
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
- free(ge->event.notify60);
- ge->event.notify60 = tmp;
- ge->event.notify60[++i].uin = 0;
- * \internal Obsługuje pakiet GG_USER_DATA.
- * Patrz gg_packet_handler_t
-static int gg_session_handle_user_data(struct gg_session *gs, uint32_t type,
- const char *ptr, size_t len, struct gg_event *ge)
- const char *p = (const char*) ptr;
- const char *packet_end = (const char*) ptr + len;
- struct gg_event_user_data_user *users;
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received user data\n");
- ge->event.user_data.user_count = 0;
- ge->event.user_data.users = NULL;
- if (ptr + sizeof(d) > packet_end)
- memcpy(&d, p, sizeof(d));
- d.type = gg_fix32(d.type);
- d.user_count = gg_fix32(d.user_count);
- if (d.user_count > 0xffff) {
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_user_data() malformed packet (1)\n");
- if (d.user_count > 0) {
- users = calloc(d.user_count, sizeof(struct gg_event_user_data_user));
- gg_debug_session(gs, GG_DEBUG_MISC,
- "// gg_session_handle_user_data() out of memory"
- " (%d*%" GG_SIZE_FMT ")\n", d.user_count,
- sizeof(struct gg_event_user_data_user));
- ge->type = GG_EVENT_USER_DATA;
- ge->event.user_data.type = d.type;
- ge->event.user_data.user_count = d.user_count;
- ge->event.user_data.users = users;
- gg_debug_session(gs, GG_DEBUG_DUMP, "type=%d, count=%d\n", d.type, d.user_count);
- for (i = 0; i < d.user_count; i++) {
- struct gg_user_data_user u;
- struct gg_event_user_data_attr *attrs;
- if (p + sizeof(u) > packet_end) {
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_user_data() malformed packet (2)\n");
- memcpy(&u, p, sizeof(u));
- u.uin = gg_fix32(u.uin);
- u.attr_count = gg_fix32(u.attr_count);
- if (u.attr_count > 0xffff) {
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_user_data() malformed packet (2)\n");
- if (u.attr_count > 0) {
- attrs = calloc(u.attr_count, sizeof(struct gg_event_user_data_attr));
- gg_debug_session(gs, GG_DEBUG_MISC,
- "// gg_session_handle_user_data() "
- "out of memory (%d*%" GG_SIZE_FMT
- sizeof(struct gg_event_user_data_attr));
- users[i].attr_count = u.attr_count;
- users[i].attrs = attrs;
- gg_debug_session(gs, GG_DEBUG_DUMP, " uin=%d, count=%d\n", u.uin, u.attr_count);
- for (j = 0; j < u.attr_count; j++) {
- if (p + sizeof(key_size) > packet_end) {
- gg_debug_session(gs, GG_DEBUG_MISC,
- "// gg_session_handle_user_data()"
- "malformed packet (3)\n");
- memcpy(&key_size, p, sizeof(key_size));
- key_size = gg_fix32(key_size);
- if (key_size > 0xffff || p + key_size > packet_end) {
- gg_debug_session(gs, GG_DEBUG_MISC,
- "// gg_session_handle_user_data() "
- "malformed packet (3)\n");
- key = malloc(key_size + 1);
- gg_debug_session(gs, GG_DEBUG_MISC,
- "// gg_session_handle_user_data() "
- "out of memory (%d)\n", key_size + 1);
- memcpy(key, p, key_size);
- if (p + sizeof(attr_type) + sizeof(value_size) > packet_end) {
- gg_debug_session(gs, GG_DEBUG_MISC,
- "// gg_session_handle_user_data() "
- "malformed packet (4)\n");
- memcpy(&attr_type, p, sizeof(attr_type));
- p += sizeof(attr_type);
- memcpy(&value_size, p, sizeof(value_size));
- p += sizeof(value_size);
- attrs[j].type = gg_fix32(attr_type);
- value_size = gg_fix32(value_size);
- if (value_size > 0xffff || p + value_size > packet_end) {
- gg_debug_session(gs, GG_DEBUG_MISC,
- "// gg_session_handle_user_data() "
- "malformed packet (5)\n");
- value = malloc(value_size + 1);
- gg_debug_session(gs, GG_DEBUG_MISC,
- "// gg_session_handle_user_data() "
- "out of memory (%d)\n", value_size + 1);
- memcpy(value, p, value_size);
- attrs[j].value = value;
- gg_debug_session(gs, GG_DEBUG_DUMP, " key=\"%s\", "
- "type=%d, value=\"%s\"\n", key, attr_type, value);
- ge->type = GG_EVENT_NONE;
- for (i = 0; i < ge->event.user_data.user_count; i++) {
- for (j = 0; j < ge->event.user_data.users[i].attr_count; j++) {
- free(ge->event.user_data.users[i].attrs[j].key);
- free(ge->event.user_data.users[i].attrs[j].value);
- free(ge->event.user_data.users[i].attrs);
- free(ge->event.user_data.users);
- * \internal Obsługuje pakiet GG_TYPING_NOTIFICATION.
- * Patrz gg_packet_handler_t
-static int gg_session_handle_typing_notification(struct gg_session *gs,
- uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
- const struct gg_typing_notification *n = (const void*) ptr;
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received typing notification\n");
- memcpy(&uin, &n->uin, sizeof(uin_t));
- ge->type = GG_EVENT_TYPING_NOTIFICATION;
- ge->event.typing_notification.uin = gg_fix32(uin);
- ge->event.typing_notification.length = gg_fix16(n->length);
- * \internal Obsługuje pakiet GG_MULTILOGON_INFO.
- * Patrz gg_packet_handler_t
-static int gg_session_handle_multilogon_info(struct gg_session *gs,
- uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
- const char *packet_end = (const char*) ptr + len;
- const struct gg_multilogon_info *info = (const struct gg_multilogon_info*) ptr;
- const char *p = (const char*) ptr + sizeof(*info);
- struct gg_multilogon_session *sessions = NULL;
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received multilogon info\n");
- count = gg_fix32(info->count);
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_handle_multilogon_info() malformed packet (1)\n");
- sessions = calloc(count, sizeof(struct gg_multilogon_session));
- if (sessions == NULL) {
- gg_debug_session(gs, GG_DEBUG_MISC, "// "
- "gg_handle_multilogon_info() out of memory (%"
- GG_SIZE_FMT "*%" GG_SIZE_FMT ")\n",
- count, sizeof(struct gg_multilogon_session));
- ge->type = GG_EVENT_MULTILOGON_INFO;
- ge->event.multilogon_info.count = count;
- ge->event.multilogon_info.sessions = sessions;
- for (i = 0; i < count; i++) {
- struct gg_multilogon_info_item item;
- if (p + sizeof(item) > packet_end) {
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_handle_multilogon_info() malformed packet (2)\n");
- memcpy(&item, p, sizeof(item));
- sessions[i].id = item.conn_id;
- sessions[i].remote_addr = item.addr;
- sessions[i].status_flags = gg_fix32(item.flags);
- sessions[i].protocol_features = gg_fix32(item.features);
- sessions[i].logon_time = gg_fix32(item.logon_time);
- name_size = gg_fix32(item.name_size);
- if (name_size > 0xffff || p + name_size > packet_end) {
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_handle_multilogon_info() malformed packet (3)\n");
- sessions[i].name = malloc(name_size + 1);
- if (sessions[i].name == NULL) {
- gg_debug_session(gs, GG_DEBUG_MISC,
- "// gg_handle_multilogon_info() out of "
- "memory (%" GG_SIZE_FMT ")\n", name_size);
- memcpy(sessions[i].name, p, name_size);
- sessions[i].name[name_size] = 0;
- ge->type = GG_EVENT_NONE;
- for (i = 0; (int) i < ge->event.multilogon_info.count; i++)
- free(ge->event.multilogon_info.sessions[i].name);
- free(ge->event.multilogon_info.sessions);
- * \internal Obsługuje pakiet GG_USERLIST100_VERSION.
- * Patrz gg_packet_handler_t
-static int gg_session_handle_userlist_100_version(struct gg_session *gs,
- uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
- const struct gg_userlist100_version *version = (const struct gg_userlist100_version*) ptr;
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received userlist 100 version\n");
- ge->type = GG_EVENT_USERLIST100_VERSION;
- ge->event.userlist100_version.version = gg_fix32(version->version);
- * \internal Obsługuje pakiet GG_USERLIST100_REPLY.
- * Patrz gg_packet_handler_t
-static int gg_session_handle_userlist_100_reply(struct gg_session *gs,
- uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
- const struct gg_userlist100_reply *reply = (const struct gg_userlist100_reply*) ptr;
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received userlist 100 reply\n");
- if (len > sizeof(*reply)) {
- data = gg_inflate((const unsigned char*) ptr + sizeof(*reply), len - sizeof(*reply));
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_handle_userlist_100_reply() gg_inflate() failed\n");
- ge->type = GG_EVENT_USERLIST100_REPLY;
- ge->event.userlist100_reply.type = reply->type;
- ge->event.userlist100_reply.version = gg_fix32(reply->version);
- ge->event.userlist100_reply.format_type = reply->format_type;
- ge->event.userlist100_reply.reply = data;
-static int gg_session_handle_imtoken(struct gg_session *gs, uint32_t type,
- const char *ptr, size_t len, struct gg_event *ge)
- GG110Imtoken *msg = gg110_imtoken__unpack(NULL, len, (uint8_t*)ptr);
- if (!GG_PROTOBUF_VALID(gs, "GG110Imtoken", msg))
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() "
- if (msg->imtoken[0] != '\0') {
- imtoken = strdup(msg->imtoken);
- succ = succ && (imtoken != NULL);
- gg110_imtoken__free_unpacked(msg, NULL);
- ge->type = GG_EVENT_IMTOKEN;
- ge->event.imtoken.imtoken = imtoken;
-static int gg_session_handle_pong_110(struct gg_session *gs, uint32_t type,
- const char *ptr, size_t len, struct gg_event *ge)
- GG110Pong *msg = gg110_pong__unpack(NULL, len, (uint8_t*)ptr);
- if (!GG_PROTOBUF_VALID(gs, "GG110Pong", msg))
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() "
- ge->type = GG_EVENT_PONG110;
- ge->event.pong110.time = msg->server_time;
- gg_sync_time(gs, msg->server_time);
- gg110_pong__free_unpacked(msg, NULL);
-static int gg_session_handle_chat_info(struct gg_session *gs, uint32_t type,
- const char *ptr, size_t len, struct gg_event *ge)
- uint32_t participants_count;
- uin_t *participants = NULL;
- tvb = gg_tvbuff_new(ptr, len);
- id = gg_tvbuff_read_uint64(tvb);
- gg_tvbuff_expected_uint32(tvb, 0); /* unknown */
- version = gg_tvbuff_read_uint32(tvb);
- dummy1 = gg_tvbuff_read_uint32(tvb);
- if (gg_tvbuff_is_valid(tvb) && dummy1 == 1) {
- name_length = gg_tvbuff_read_uint32(tvb);
- gg_tvbuff_skip(tvb, name_length);
- gg_tvbuff_expected_uint32(tvb, 0); /* unknown */
- gg_tvbuff_expected_uint32(tvb, 2); /* unknown */
- participants_count = gg_tvbuff_read_uint32(tvb);
- if (id == 0 && participants_count > 0) {
- gg_debug_session(gs, GG_DEBUG_MISC | GG_DEBUG_WARNING,
- "// gg_session_handle_chat_info() terminating packet "
- "shouldn't contain participants\n");
- participants_count = 0;
- if (participants_count > 0) {
- participants = malloc(sizeof(uin_t) * participants_count);
- if (participants == NULL) {
- for (i = 0; i < participants_count && gg_tvbuff_is_valid(tvb); i++) {
- participants[i] = gg_tvbuff_read_uint32(tvb);
- gg_tvbuff_read_uint32(tvb); /* 0x1e lub 0x18 */
- if (!gg_tvbuff_close(tvb)) {
- ge->type = GG_EVENT_CHAT_INFO_GOT_ALL;
- if (0 != gg_chat_update(gs, id, version, participants,
- ge->type = GG_EVENT_CHAT_INFO;
- ge->event.chat_info.id = id;
- ge->event.chat_info.version = version;
- ge->event.chat_info.participants_count = participants_count;
- ge->event.chat_info.participants = participants;
-static int gg_session_handle_chat_info_update(struct gg_session *gs,
- uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
- GG110ChatInfoUpdate *msg = gg110_chat_info_update__unpack(NULL, len, (uint8_t*)ptr);
- if (!GG_PROTOBUF_VALID(gs, "GG110ChatInfoUpdate", msg))
- gg_debug_session(gs, GG_DEBUG_VERBOSE,
- "// gg_session_handle_chat_info_update() "
- "msg_id=%016" PRIx64 " conv_id=%016" PRIx64 "\n",
- msg->msg_id, msg->conv_id);
- ge->type = GG_EVENT_CHAT_INFO_UPDATE;
- ge->event.chat_info_update.id = msg->chat_id;
- ge->event.chat_info_update.type = msg->update_type;
- ge->event.chat_info_update.participant = participant = gg_protobuf_get_uin(msg->participant);
- ge->event.chat_info_update.inviter = gg_protobuf_get_uin(msg->inviter);
- ge->event.chat_info_update.version = msg->version;
- ge->event.chat_info_update.time = msg->time;
- chat = gg_chat_find(gs, msg->chat_id);
- gg110_chat_info_update__free_unpacked(msg, NULL);
- chat->version = msg->version;
- if (msg->update_type == GG_CHAT_INFO_UPDATE_ENTERED) {
- uin_t *old_part = chat->participants;
- chat->participants = realloc(chat->participants,
- sizeof(uin_t) * chat->participants_count);
- if (chat->participants == NULL) {
- chat->participants = old_part;
- gg_debug_session(gs, GG_DEBUG_ERROR,
- "// gg_session_handle_chat_info_update() "
- "out of memory (count=%u)\n",
- chat->participants_count);
- chat->participants_count++;
- chat->participants[chat->participants_count - 1] = participant;
- } else if (msg->update_type == GG_CHAT_INFO_UPDATE_EXITED) {
- for (idx = 0; idx < chat->participants_count; idx++)
- if (chat->participants[idx] == participant)
- if (chat->participants_count > 1 &&
- idx < chat->participants_count)
- chat->participants[idx] = chat->participants[chat->participants_count - 1];
- if (idx < chat->participants_count) {
- chat->participants_count--;
- if (chat->participants_count == 0) {
- free(chat->participants);
- chat->participants = NULL;
- chat->participants = realloc(chat->participants,
- sizeof(uin_t)*chat->participants_count);
- gg110_chat_info_update__free_unpacked(msg, NULL);
-static int gg_session_handle_chat_created(struct gg_session *gs, uint32_t type,
- const char *ptr, size_t len, struct gg_event *ge)
- const struct gg_chat_created *p = (const struct gg_chat_created *)ptr;
- if (0 != gg_chat_update(gs, gg_fix64(p->id), 0, &gs->uin, 1))
- ge->type = GG_EVENT_CHAT_CREATED;
- ge->event.chat_created.id = gg_fix64(p->id);
- ge->event.chat_created.seq = gg_fix32(p->seq);
-static int gg_session_handle_chat_invite_ack(struct gg_session *gs,
- uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
- const struct gg_chat_invite_ack *p =
- (const struct gg_chat_invite_ack *)ptr;
- ge->type = GG_EVENT_CHAT_INVITE_ACK;
- ge->event.chat_invite_ack.id = gg_fix64(p->id);
- ge->event.chat_invite_ack.seq = gg_fix32(p->seq);
-static int gg_session_handle_chat_left(struct gg_session *gs, uint32_t type,
- const char *ptr, size_t len, struct gg_event *ge)
- const struct gg_chat_left *p = (const struct gg_chat_left *)ptr;
- ge->type = GG_EVENT_CHAT_INFO_UPDATE;
- ge->event.chat_info_update.id = gg_fix64(p->id);
- ge->event.chat_info_update.type = GG_CHAT_INFO_UPDATE_EXITED;
- /* Właściwie, to nie wiadomo, czy to jest "osoba wychodząca", czy
- * "osoba wyrzucająca nas" z konferencji. */
- ge->event.chat_info_update.participant = gg_fix32(p->uin);
- ge->event.chat_info_update.inviter = gg_fix32(p->uin);
- ge->event.chat_info_update.version = 0;
- ge->event.chat_info_update.time = time(NULL);
-static int gg_session_handle_options(struct gg_session *gs, uint32_t type,
- const char *ptr, size_t len, struct gg_event *ge)
- GG110Options *msg = gg110_options__unpack(NULL, len, (uint8_t*)ptr);
- if (!GG_PROTOBUF_VALID(gs, "GG110Options", msg))
- gg_protobuf_expected(gs, "GG110Options.dummy1", msg->dummy1, 0);
- for (i = 0; i < msg->n_options; i++) {
- ProtobufKVP *kvp = msg->options[i];
- if (!GG_PROTOBUF_VALID(gs, "ProtobufKVP", kvp))
- gg_debug_session(gs, GG_DEBUG_MISC,
- "// gg_session_handle_options[%s] = \"%s\"\n",
- gg110_options__free_unpacked(msg, NULL);
-static int gg_session_handle_access_info(struct gg_session *gs, uint32_t type,
- const char *ptr, size_t len, struct gg_event *ge)
- GG110AccessInfo *msg = gg110_access_info__unpack(NULL, len, (uint8_t*)ptr);
- if (!GG_PROTOBUF_VALID(gs, "GG110AccessInfo", msg))
- gg_debug_session(gs, GG_DEBUG_MISC,
- "// gg_session_handle_access_info: dummy[%02x, %02x], "
- "last[message=%u, file_transfer=%u, conference_ch=%u]\n",
- msg->dummy1, msg->dummy2, msg->last_message,
- msg->last_file_transfer, msg->last_conference_ch);
- gg110_access_info__free_unpacked(msg, NULL);
-/* ten pakiet jest odbierany tylko, jeżeli przy logowaniu użyliśmy identyfikatora typu 0x01 */
-static int gg_session_handle_uin_info(struct gg_session *gs, uint32_t type,
- const char *ptr, size_t len, struct gg_event *ge)
- char *uin1 = NULL, *uin2 = NULL;
- tvb = gg_tvbuff_new(ptr, len);
- gg_tvbuff_expected_uint32(tvb, 1); /* unknown */
- gg_tvbuff_expected_uint32(tvb, 2); /* unknown */
- /* podstawowy identyfikator (numer GG) */
- gg_tvbuff_expected_uint8(tvb, 0);
- gg_tvbuff_read_str_dup(tvb, &uin1);
- /* identyfikator użyty przy logowaniu (numer GG lub email) */
- gg_tvbuff_expected_uint8(tvb, 1);
- gg_tvbuff_read_str_dup(tvb, &uin2);
- if (!gg_tvbuff_close(tvb)) {
- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_uin_info: "
- "uin1=\"%s\", uin2=\"%s\"\n", uin1, uin2);
-static int gg_session_handle_transfer_info(struct gg_session *gs, uint32_t type,
- const char *ptr, size_t len, struct gg_event *ge)
- GG112TransferInfo *msg = gg112_transfer_info__unpack(NULL, len, (uint8_t*)ptr);
- uin_t peer = 0, sender = 0;
- if (!GG_PROTOBUF_VALID(gs, "GG112TransferInfo", msg))
- /* see packets.proto */
- if (msg->dummy1 != 5 && msg->dummy1 != 6) {
- gg_debug_session(gs, GG_DEBUG_MISC | GG_DEBUG_WARNING,
- "// gg_session_handle_transfer_info: "
- "unknown dummy1 value: %d\n", msg->dummy1);
- if (GG_PROTOBUF_VALID(gs, "GG112TransferInfoUin", msg->peer)) {
- gg_protobuf_expected(gs, "GG112TransferInfoUin.dummy1",
- peer = gg_protobuf_get_uin(msg->peer->uin);
- if (GG_PROTOBUF_VALID(gs, "GG112TransferInfoUin", msg->sender)) {
- gg_protobuf_expected(gs, "GG112TransferInfoUin.dummy1",
- msg->sender->dummy1, 1);
- sender = gg_protobuf_get_uin(msg->sender->uin);
- gg_debug_session(gs, GG_DEBUG_MISC,
- "// gg_session_handle_transfer_info: dummy1=%#x, time=%u, "
- "sender=%u, peer=%u, msg_id=%#016" PRIx64 ", "
- "conv_id=%#016" PRIx64 "\n",
- msg->dummy1, msg->time, sender, peer, msg->msg_id,
- for (i = 0; i < msg->n_data; i++) {
- ProtobufKVP *kvp = msg->data[i];
- if (!GG_PROTOBUF_VALID(gs, "ProtobufKVP", kvp))
- gg_debug_session(gs, GG_DEBUG_MISC,
- "// gg_session_handle_transfer_info[%s] = \"%s\"\n",
- if (msg->file && GG_PROTOBUF_VALID(gs, "GG112TransferInfoFile", msg->file)) {
- GG112TransferInfoFile *file = msg->file;
- gg_debug_session(gs, GG_DEBUG_MISC,
- "// gg_session_handle_transfer_info file: "
- "type=\"%s\", content_type=\"%s\", filename=\"%s\", "
- "filesize=%u, msg_id=%#016" PRIx64 " url=\"%s\"\n",
- file->type, file->content_type, file->filename,
- file->filesize, file->msg_id, file->url);
- succ = (gg_ack_110(gs, GG110_ACK__TYPE__TRANSFER_INFO,
- gg112_transfer_info__free_unpacked(msg, NULL);
-static int gg_session_handle_magic_notification(struct gg_session *gs, uint32_t type,
- const char *ptr, size_t len, struct gg_event *ge)
- GG110MagicNotification *msg = gg110_magic_notification__unpack(NULL, len, (uint8_t*)ptr);
- if (!GG_PROTOBUF_VALID(gs, "GG110MagicNotification", msg))
- gg_debug_session(gs, GG_DEBUG_MISC,
- "// gg_session_handle_magic_notification \n");
- gg_protobuf_expected(gs, "GG110MagicNotification.dummy1", msg->dummy1, 2);
- gg_protobuf_expected(gs, "GG110MagicNotification.dummy2", msg->dummy2, 1);
- gg_protobuf_expected(gs, "GG110MagicNotification.dummy3", msg->dummy3, 1);
- succ = (gg_ack_110(gs, GG110_ACK__TYPE__MAGIC_NOTIFICATION, msg->seq, ge) == 0);
- gg110_magic_notification__free_unpacked(msg, NULL);
- * \internal Tablica obsługiwanych pakietów
-static const gg_packet_handler_t handlers[] =
- /* style:maxlinelength:start-ignore */
- { GG_WELCOME, GG_STATE_READING_KEY, 0, gg_session_handle_welcome },
- { GG_LOGIN_OK, GG_STATE_READING_REPLY, 0, gg_session_handle_login_ok },
- { GG_LOGIN80_OK, GG_STATE_READING_REPLY, 0, gg_session_handle_login_ok },
- { GG_LOGIN110_OK, GG_STATE_READING_REPLY, 0, gg_session_handle_login110_ok },
- { GG_NEED_EMAIL, GG_STATE_READING_REPLY, 0, gg_session_handle_login_ok },
- { GG_LOGIN_FAILED, GG_STATE_READING_REPLY, 0, gg_session_handle_login_failed },
- { GG_LOGIN80_FAILED, GG_STATE_READING_REPLY, 0, gg_session_handle_login_failed },
- { GG_SEND_MSG_ACK, GG_STATE_CONNECTED, sizeof(struct gg_send_msg_ack), gg_session_handle_send_msg_ack },
- { GG_SEND_MSG_ACK110, GG_STATE_CONNECTED, 0, gg_session_handle_send_msg_ack_110 },
- { GG_PONG, GG_STATE_CONNECTED, 0, gg_session_handle_pong },
- { GG_DISCONNECTING, GG_STATE_CONNECTED, 0, gg_session_handle_disconnecting },
- { GG_DISCONNECT_ACK, GG_STATE_DISCONNECTING, 0, gg_session_handle_disconnect_ack },
- { GG_XML_EVENT, GG_STATE_CONNECTED, 0, gg_session_handle_xml_event },
- { GG_EVENT110, GG_STATE_CONNECTED, 0, gg_session_handle_event_110 },
- { GG_PUBDIR50_REPLY, GG_STATE_CONNECTED, 0, gg_session_handle_pubdir50_reply },
- { GG_USERLIST_REPLY, GG_STATE_CONNECTED, sizeof(char), gg_session_handle_userlist_reply },
- { GG_DCC7_ID_REPLY, GG_STATE_CONNECTED, sizeof(struct gg_dcc7_id_reply), gg_session_handle_dcc7_id_reply },
- { GG_DCC7_ACCEPT, GG_STATE_CONNECTED, sizeof(struct gg_dcc7_accept), gg_session_handle_dcc7_accept },
- { GG_DCC7_NEW, GG_STATE_CONNECTED, sizeof(struct gg_dcc7_new), gg_session_handle_dcc7_new },
- { GG_DCC7_REJECT, GG_STATE_CONNECTED, sizeof(struct gg_dcc7_reject), gg_session_handle_dcc7_reject },
- { GG_DCC7_INFO, GG_STATE_CONNECTED, sizeof(struct gg_dcc7_info), gg_session_handle_dcc7_info },
- { GG_RECV_MSG, GG_STATE_CONNECTED, sizeof(struct gg_recv_msg), gg_session_handle_recv_msg },
- { GG_RECV_MSG80, GG_STATE_CONNECTED, sizeof(struct gg_recv_msg80), gg_session_handle_recv_msg_80 },
- { GG_RECV_MSG110, GG_STATE_CONNECTED, 0, gg_session_handle_recv_msg_110 },
- { GG_RECV_OWN_MSG110, GG_STATE_CONNECTED, 0, gg_session_handle_recv_msg_110 },
- { GG_STATUS, GG_STATE_CONNECTED, sizeof(struct gg_status), gg_session_handle_status },
- { GG_STATUS60, GG_STATE_CONNECTED, sizeof(struct gg_status60), gg_session_handle_status_60_77_80beta },
- { GG_STATUS77, GG_STATE_CONNECTED, sizeof(struct gg_status77), gg_session_handle_status_60_77_80beta },
- { GG_STATUS80BETA, GG_STATE_CONNECTED, sizeof(struct gg_status77), gg_session_handle_status_60_77_80beta },
- { GG_STATUS80, GG_STATE_CONNECTED, sizeof(struct gg_notify_reply80), gg_session_handle_status_80 },
- { GG_NOTIFY_REPLY, GG_STATE_CONNECTED, sizeof(struct gg_notify_reply), gg_session_handle_notify_reply },
- { GG_NOTIFY_REPLY60, GG_STATE_CONNECTED, sizeof(struct gg_notify_reply60), gg_session_handle_notify_reply_60 },
- { GG_NOTIFY_REPLY77, GG_STATE_CONNECTED, sizeof(struct gg_notify_reply77), gg_session_handle_notify_reply_77_80beta },
- { GG_NOTIFY_REPLY80BETA, GG_STATE_CONNECTED, sizeof(struct gg_notify_reply77), gg_session_handle_notify_reply_77_80beta },
- { GG_NOTIFY_REPLY80, GG_STATE_CONNECTED, sizeof(struct gg_notify_reply80), gg_session_handle_notify_reply_80 },
- { GG_USER_DATA, GG_STATE_CONNECTED, sizeof(struct gg_user_data), gg_session_handle_user_data },
- { GG_TYPING_NOTIFICATION, GG_STATE_CONNECTED, sizeof(struct gg_typing_notification), gg_session_handle_typing_notification },
- { GG_MULTILOGON_INFO, GG_STATE_CONNECTED, sizeof(struct gg_multilogon_info), gg_session_handle_multilogon_info },
- { GG_XML_ACTION, GG_STATE_CONNECTED, 0, gg_session_handle_xml_event },
- { GG_RECV_OWN_MSG, GG_STATE_CONNECTED, sizeof(struct gg_recv_msg80), gg_session_handle_recv_msg_80 },
- { GG_USERLIST100_VERSION, GG_STATE_CONNECTED, sizeof(struct gg_userlist100_version), gg_session_handle_userlist_100_version },
- { GG_USERLIST100_REPLY, GG_STATE_CONNECTED, sizeof(struct gg_userlist100_reply), gg_session_handle_userlist_100_reply },
- { GG_IMTOKEN, GG_STATE_CONNECTED, 0, gg_session_handle_imtoken },
- { GG_PONG110, GG_STATE_CONNECTED, 0, gg_session_handle_pong_110 },
- { GG_CHAT_INFO, GG_STATE_CONNECTED, 0, gg_session_handle_chat_info },
- { GG_CHAT_INFO_UPDATE, GG_STATE_CONNECTED, 0, gg_session_handle_chat_info_update },
- { GG_CHAT_CREATED, GG_STATE_CONNECTED, sizeof(struct gg_chat_created), gg_session_handle_chat_created },
- { GG_CHAT_INVITE_ACK, GG_STATE_CONNECTED, sizeof(struct gg_chat_invite_ack), gg_session_handle_chat_invite_ack },
- { GG_CHAT_RECV_MSG, GG_STATE_CONNECTED, 0, gg_session_handle_recv_msg_110 },
- { GG_CHAT_RECV_OWN_MSG, GG_STATE_CONNECTED, 0, gg_session_handle_recv_msg_110 },
- { GG_CHAT_LEFT, GG_STATE_CONNECTED, sizeof(struct gg_chat_left), gg_session_handle_chat_left },
- { GG_OPTIONS, GG_STATE_CONNECTED, 0, gg_session_handle_options },
- { GG_ACCESS_INFO, GG_STATE_CONNECTED, 0, gg_session_handle_access_info },
- { GG_UIN_INFO, GG_STATE_CONNECTED, 0, gg_session_handle_uin_info },
- { GG_TRANSFER_INFO, GG_STATE_CONNECTED, 0, gg_session_handle_transfer_info },
- { GG_MAGIC_NOTIFICATION, GG_STATE_CONNECTED, 0, gg_session_handle_magic_notification }
- /* style:maxlinelength:end-ignore */
- * \internal Obsługuje przychodzący pakiet danych.
- * \param gs Struktura sesji
- * \param type Typ pakietu
- * \param ptr Wskaźnik do bufora pakietu
- * \param len Długość bufora pakietu
- * \param[out] ge Struktura zdarzenia
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_session_handle_packet(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
- gg_debug_session(gs, GG_DEBUG_FUNCTION,
- "// gg_session_handle_packet(%d, %p, %" GG_SIZE_FMT ")\n",
- gs->last_event = time(NULL);
- if ((gs->flags & (1 << GG_SESSION_FLAG_RAW_PACKET)) != 0) {
- gg_debug_session(gs, GG_DEBUG_ERROR,
- "// gg_session_handle_packet() out of memory "
- ge->type = GG_EVENT_RAW_PACKET;
- ge->event.raw_packet.type = type;
- ge->event.raw_packet.length = len;
- ge->event.raw_packet.data = tmp;
- for (i = 0; i < sizeof(handlers) / sizeof(handlers[0]); i++) {
- if (handlers[i].type != 0 && handlers[i].type != type)
- if (handlers[i].state != 0 && handlers[i].state != (enum gg_state_t) gs->state) {
- gg_debug_session(gs, GG_DEBUG_WARNING,
- "// gg_session_handle_packet() packet 0x%02x "
- "unexpected in state %d\n", type, gs->state);
- if (len < handlers[i].min_length) {
- gg_debug_session(gs, GG_DEBUG_ERROR,
- "// gg_session_handle_packet() packet 0x%02x "
- "too short (%" GG_SIZE_FMT " bytes)\n",
- return (*handlers[i].handler)(gs, type, ptr, len, ge);
- gg_debug_session(gs, GG_DEBUG_WARNING, "// gg_session_handle_packet() "
- "unhandled packet 0x%02x, len %" GG_SIZE_FMT ", state %d\n",
--- a/libpurple/protocols/gg/lib/http.c Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,592 +0,0 @@
- * (C) Copyright 2001-2002 Wojtek Kaniewski <wojtekka@irc.pl>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
- * \brief Obsługa połączeń HTTP
-#define GG_HTTP_MAX_LENGTH 1000000000
- * Rozpoczyna połączenie HTTP.
- * Funkcja przeprowadza połączenie HTTP przy połączeniu synchronicznym,
- * zwracając wynik w polach struktury \c gg_http, lub błąd, gdy sesja się
- * Przy połączeniu asynchronicznym, funkcja rozpoczyna połączenie, a dalsze
- * etapy będą przeprowadzane po wykryciu zmian (\c watch) na obserwowanym
- * deskryptorze (\c fd) i wywołaniu funkcji \c gg_http_watch_fd().
- * Po zakończeniu, należy zwolnić strukturę za pomocą funkcji
- * \c gg_http_free(). Połączenie asynchroniczne można zatrzymać w każdej
- * chwili za pomocą \c gg_http_stop().
- * \param hostname Adres serwera
- * \param port Port serwera
- * \param async Flaga asynchronicznego połączenia
- * \param method Metoda HTTP
- * \param path Ścieżka do zasobu (musi być poprzedzona znakiem '/')
- * \param header Nagłówek zapytania plus ewentualne dane dla POST
- * \return Zaalokowana struktura \c gg_http lub NULL, jeśli wystąpił błąd.
-struct gg_http *gg_http_connect(const char *hostname, int port, int async,
- const char *method, const char *path, const char *header)
- if (!hostname || !port || !method || !path || !header) {
- gg_debug(GG_DEBUG_MISC, "// gg_http_connect() invalid arguments\n");
- if (!(h = malloc(sizeof(*h))))
- memset(h, 0, sizeof(*h));
- h->type = GG_SESSION_HTTP;
- gg_http_set_resolver(h, GG_RESOLVER_DEFAULT);
- if (gg_proxy_enabled) {
- char *auth = gg_proxy_auth();
- h->query = gg_saprintf("%s http://%s:%d%s HTTP/1.0\r\n%s%s",
- method, hostname, port, path, (auth) ? auth :
- hostname = gg_proxy_host;
- h->port = port = gg_proxy_port;
- h->query = gg_saprintf("%s %s HTTP/1.0\r\n%s",
- if (h->query == NULL) {
- gg_debug(GG_DEBUG_MISC, "// gg_http_connect() not enough memory for query\n");
- gg_debug(GG_DEBUG_MISC, "=> -----BEGIN-HTTP-QUERY-----\n%s\n=> -----END-HTTP-QUERY-----\n", h->query);
- if (h->resolver_start(&h->fd, &h->resolver, hostname) == -1) {
- gg_debug(GG_DEBUG_MISC, "// gg_http_connect() resolver failed\n");
- gg_debug(GG_DEBUG_MISC, "// gg_http_connect() resolver = %p\n", h->resolver);
- h->state = GG_STATE_RESOLVING;
- h->check = GG_CHECK_READ;
- h->timeout = GG_DEFAULT_TIMEOUT;
- struct in_addr *addr_list = NULL;
- unsigned int addr_count;
- if (gg_gethostbyname_real(hostname, &addr_list, &addr_count, 0) == -1 || addr_count == 0) {
- gg_debug(GG_DEBUG_MISC, "// gg_http_connect() host not found\n");
- h->fd = gg_connect(&addr_list[0], port, 0);
- gg_debug(GG_DEBUG_MISC, "// gg_http_connect() "
- "connection failed (errno=%d, %s)\n",
- errno, strerror(errno));
- h->state = GG_STATE_CONNECTING;
- while (h->state != GG_STATE_ERROR && h->state != GG_STATE_PARSING) {
- if (gg_http_watch_fd(h) == -1)
- if (h->state != GG_STATE_PARSING) {
- gg_debug(GG_DEBUG_MISC, "// gg_http_connect() some strange error\n");
- h->callback = gg_http_watch_fd;
- h->destroy = gg_http_free;
-#define gg_http_error(x) \
- h->state = GG_STATE_ERROR; \
- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
- * Operacja będzie zakończona, gdy pole \c state będzie równe
- * \c GG_STATE_PARSING. W tym miejscu działanie przejmuje zwykle funkcja
- * korzystająca z \c gg_http_watch_fd(). W przypadku błędu połączenia,
- * pole \c state będzie równe \c GG_STATE_ERROR, a kod błędu znajdzie się
- * \param h Struktura połączenia
- * \return \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_http_watch_fd(struct gg_http *h)
- gg_debug(GG_DEBUG_FUNCTION, "** gg_http_watch_fd(%p);\n", h);
- gg_debug(GG_DEBUG_MISC, "// gg_http_watch_fd() invalid arguments\n");
- if (h->state == GG_STATE_RESOLVING) {
- gg_debug(GG_DEBUG_MISC, "=> http, resolving done\n");
- res = gg_resolver_recv(h->fd, &addr, sizeof(addr));
- } while (res == -1 && errno == EINTR);
- h->resolver_cleanup(&h->resolver, 0);
- if (res != sizeof(addr) || addr.s_addr == INADDR_NONE) {
- gg_debug(GG_DEBUG_MISC, "=> http, resolver thread failed\n");
- gg_http_error(GG_ERROR_RESOLVING);
- gg_debug(GG_DEBUG_MISC, "=> http, connecting to %s:%d\n", inet_ntoa(addr), h->port);
- h->fd = gg_connect(&addr, h->port, h->async);
- gg_debug(GG_DEBUG_MISC, "=> http, connection failed (errno=%d, %s)\n", errno, strerror(errno));
- gg_http_error(GG_ERROR_CONNECTING);
- h->state = GG_STATE_CONNECTING;
- h->check = GG_CHECK_WRITE;
- h->timeout = GG_DEFAULT_TIMEOUT;
- if (h->state == GG_STATE_CONNECTING) {
- socklen_t res_size = sizeof(res);
- if (h->async && (getsockopt(h->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res)) {
- gg_debug(GG_DEBUG_MISC, "=> http, async connection "
- "failed (errno=%d, %s)\n", (res) ? res : errno,
- strerror((res) ? res : errno));
- h->state = GG_STATE_ERROR;
- h->error = GG_ERROR_CONNECTING;
- gg_debug(GG_DEBUG_MISC, "=> http, connected, sending request\n");
- h->state = GG_STATE_SENDING_QUERY;
- if (h->state == GG_STATE_SENDING_QUERY) {
- res = send(h->fd, h->query, strlen(h->query), 0);
- if (res == -1 && errno != EINTR && errno != EAGAIN) {
- gg_debug(GG_DEBUG_MISC, "=> http, send() failed "
- "(len=%" GG_SIZE_FMT ", res=%d, errno=%d)\n",
- strlen(h->query), res, errno);
- gg_http_error(GG_ERROR_WRITING);
- gg_debug(GG_DEBUG_MISC, "=> http, non-critical send "
- "error (errno=%d, %s)\n",
- errno, strerror(errno));
- if ((size_t) res < strlen(h->query)) {
- gg_debug(GG_DEBUG_MISC, "=> http, partial header sent "
- "(led=%" GG_SIZE_FMT ", sent=%d)\n",
- strlen(h->query), res);
- memmove(h->query, h->query + res, strlen(h->query) - res + 1);
- h->state = GG_STATE_SENDING_QUERY;
- h->check = GG_CHECK_WRITE;
- h->timeout = GG_DEFAULT_TIMEOUT;
- gg_debug(GG_DEBUG_MISC, "=> http, request sent (len=%"
- GG_SIZE_FMT ")\n", strlen(h->query));
- h->state = GG_STATE_READING_HEADER;
- h->check = GG_CHECK_READ;
- h->timeout = GG_DEFAULT_TIMEOUT;
- if (h->state == GG_STATE_READING_HEADER) {
- res = recv(h->fd, buf, sizeof(buf), 0);
- if (res == -1 && errno != EINTR && errno != EAGAIN) {
- gg_debug(GG_DEBUG_MISC, "=> http, reading header failed (errno=%d)\n", errno);
- gg_http_error(GG_ERROR_READING);
- gg_debug(GG_DEBUG_MISC, "=> http, non-critical recv "
- "error (errno=%d, %s)\n",
- errno, strerror(errno));
- gg_debug(GG_DEBUG_MISC, "=> http, connection reset by peer\n");
- gg_http_error(GG_ERROR_READING);
- gg_debug(GG_DEBUG_MISC, "=> http, read %d bytes of header\n", res);
- tmp = realloc(h->header, h->header_size + res + 1);
- gg_debug(GG_DEBUG_MISC, "=> http, not enough memory for header\n");
- gg_http_error(GG_ERROR_READING);
- memcpy(h->header + h->header_size, buf, res);
- gg_debug(GG_DEBUG_MISC, "=> http, header_buf=%p, header_size=%d\n", h->header, h->header_size);
- h->header[h->header_size] = 0;
- if ((tmp = strstr(h->header, "\r\n\r\n")) || (tmp = strstr(h->header, "\n\n"))) {
- int sep_len = (*tmp == '\r') ? 4 : 2;
- left = h->header_size - ((size_t)(tmp) - (size_t)(h->header) + sep_len);
- gg_debug(GG_DEBUG_MISC, "=> http, got all header "
- "(%d bytes, %d left)\n",
- h->header_size - left, left);
- if (strlen(h->header) < 16 || strncmp(h->header + 9, "200", 3)) {
- gg_debug(GG_DEBUG_MISC,
- "=> -----BEGIN-HTTP-HEADER-----\n%s\n"
- "=> -----END-HTTP-HEADER-----\n",
- gg_debug(GG_DEBUG_MISC, "=> http, didn't get 200 OK -- no results\n");
- gg_http_error(GG_ERROR_CONNECTING);
- gg_debug(GG_DEBUG_MISC, "=> -----BEGIN-HTTP-HEADER-----"
- "\n%s\n=> -----END-HTTP-HEADER-----\n",
- if (!strncasecmp(line, "Content-length: ", 16)) {
- h->body_size = atoi(line + 16);
- line = strchr(line, '\n');
- if (h->body_size <= 0) {
- gg_debug(GG_DEBUG_MISC, "=> http, content-length not found\n");
- if (h->body_size > GG_HTTP_MAX_LENGTH) {
- gg_debug(GG_DEBUG_MISC, "=> http, content-length too big\n");
- h->body_size = GG_HTTP_MAX_LENGTH;
- if (left > h->body_size) {
- gg_debug(GG_DEBUG_MISC, "=> http, oversized "
- "reply (%d bytes needed, "
- "%d bytes left)\n", h->body_size, left);
- gg_debug(GG_DEBUG_MISC, "=> http, body_size=%d\n", h->body_size);
- if (!(h->body = malloc(h->body_size + 1))) {
- gg_debug(GG_DEBUG_MISC, "=> http, not enough "
- "memory (%d bytes for body_buf)\n",
- gg_http_error(GG_ERROR_READING);
- memcpy(h->body, tmp + sep_len, left);
- h->state = GG_STATE_READING_DATA;
- h->check = GG_CHECK_READ;
- h->timeout = GG_DEFAULT_TIMEOUT;
- if (h->state == GG_STATE_READING_DATA) {
- res = recv(h->fd, buf, sizeof(buf), 0);
- if (res == -1 && errno != EINTR && errno != EAGAIN) {
- gg_debug(GG_DEBUG_MISC, "=> http, reading body failed (errno=%d)\n", errno);
- gg_http_error(GG_ERROR_READING);
- gg_debug(GG_DEBUG_MISC, "=> http, non-critical "
- "recv error (errno=%d, %s)\n",
- errno, strerror(errno));
- if (h->body_done >= h->body_size) {
- gg_debug(GG_DEBUG_MISC, "=> http, we're done, closing socket\n");
- h->state = GG_STATE_PARSING;
- gg_debug(GG_DEBUG_MISC, "=> http, "
- "connection closed while reading "
- "(have %d, need %d)\n",
- h->body_done, h->body_size);
- gg_http_error(GG_ERROR_READING);
- gg_debug(GG_DEBUG_MISC, "=> http, read %d bytes of body\n", res);
- if (h->body_done + res > h->body_size) {
- gg_debug(GG_DEBUG_MISC, "=> http, too much data "
- "(%d bytes, %d needed), enlarging buffer\n",
- h->body_done + res, h->body_size);
- if (!(tmp = realloc(h->body, h->body_done + res + 1))) {
- gg_debug(GG_DEBUG_MISC, "=> http, not enough "
- "memory for data (%d needed)\n",
- h->body_done + res + 1);
- gg_http_error(GG_ERROR_READING);
- h->body_size = h->body_done + res;
- h->body[h->body_done + res] = 0;
- memcpy(h->body + h->body_done, buf, res);
- gg_debug(GG_DEBUG_MISC, "=> body_done=%d, body_size=%d\n", h->body_done, h->body_size);
- h->state = GG_STATE_ERROR;
- * Kończy asynchroniczne połączenie HTTP.
- * Po zatrzymaniu należy zwolnić zasoby funkcją \c gg_http_free().
- * \param h Struktura połączenia
-void gg_http_stop(struct gg_http *h)
- if (h->state == GG_STATE_ERROR || h->state == GG_STATE_DONE)
- h->resolver_cleanup(&h->resolver, 1);
- * \internal Zwalnia pola struktury \c gg_http.
- * Funkcja zwalnia same pola, nie zwalnia struktury.
- * \param h Struktura połączenia
-void gg_http_free_fields(struct gg_http *h)
- * Zwalnia zasoby po połączeniu HTTP.
- * Jeśli połączenie nie zostało jeszcze zakończone, jest przerywane.
- * \param h Struktura połączenia
-void gg_http_free(struct gg_http *h)
- gg_http_free_fields(h);
- * c-indentation-style: k&r
- * indent-tabs-mode: notnil
--- a/libpurple/protocols/gg/lib/internal.h Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,266 +0,0 @@
- * (C) Copyright 2009 Jakub Zawadzki <darkjames@darkjames.ath.cx>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-#ifndef LIBGADU_INTERNAL_H
-#define LIBGADU_INTERNAL_H
-#define GG_DEFAULT_CLIENT_VERSION_100 "10.1.0.11070"
-#define GG_DEFAULT_CLIENT_VERSION_110 "11.3.45.10771"
-# define GG_SIZE_FMT "lu"
-# define _GG_INT64_MODIFIER "ll"
-# define GG_SIZE_FMT "Iu"
-# define _GG_INT64_MODIFIER "I64"
-# define GG_SIZE_FMT "zu"
-# define _GG_INT64_MODIFIER "l"
-# define GG_SIZE_FMT "zu"
-# define _GG_INT64_MODIFIER "ll"
-# define PRIu64 _GG_INT64_MODIFIER "u"
-# define PRIx64 _GG_INT64_MODIFIER "x"
-# define PRId64 _GG_INT64_MODIFIER "d"
-#define GG_LOGIN_PARAMS_HAS_FIELD(glp, member) \
- (offsetof(struct gg_login_params, member) < (glp)->struct_size || \
- offsetof(struct gg_login_params, member) <= offsetof(struct gg_login_params, struct_size))
-# define GG_UNUSED __attribute__ ((unused))
-# define GG_NORETURN __attribute__ ((noreturn))
-# define GG_CDECL __attribute__ ((__cdecl__))
-#define GG_STATIC_ASSERT(condition, message) \
- { typedef char static_assertion_failed_ ## message \
- [(condition) ? 1 : -1]; static_assertion_failed_ ## message dummy; \
-#define GG_IMGOUT_WAITING_MAX 4
-typedef struct _gg_chat_list gg_chat_list_t;
- uint32_t participants_count;
-typedef struct _gg_msg_list gg_msg_list_t;
- size_t recipients_count;
-typedef struct _gg_eventqueue gg_eventqueue_t;
- struct gg_event *event;
-typedef struct _gg_imgout_queue_t gg_imgout_queue_t;
-struct _gg_imgout_queue_t {
- struct gg_send_msg msg_hdr;
- gg_imgout_queue_t *next;
-struct gg_session_private {
- gg_compat_t compatibility;
- gg_chat_list_t *chat_list;
- gg_msg_list_t *sent_messages;
- gg_eventqueue_t *event_queue;
- gg_imgout_queue_t *imgout_queue;
- int imgout_waiting_ack;
- gg_socket_manager_type_t socket_manager_type;
- gg_socket_manager_t socket_manager;
- int socket_is_external;
- enum gg_failure_t socket_failure;
- char **host_white_list;
- GG_COMPAT_FEATURE_ACK_EVENT,
- GG_COMPAT_FEATURE_LEGACY_CONFER
-typedef struct gg_dcc7_relay gg_dcc7_relay_t;
-void * gg_new0(size_t size);
-int gg_required_proto(struct gg_session *gs, int protocol_version);
-int gg_get_dummy_fd(struct gg_session *sess);
-int gg_compat_feature_is_enabled(struct gg_session *sess, gg_compat_feature_t feature);
-int gg_pubdir50_handle_reply_sess(struct gg_session *sess, struct gg_event *e, const char *packet, int length);
-int gg_resolve(int *fd, int *pid, const char *hostname);
-int gg_resolve_pthread(int *fd, void **resolver, const char *hostname);
-void gg_resolve_pthread_cleanup(void *resolver, int kill);
-int gg_login_hash_sha1_2(const char *password, uint32_t seed, uint8_t *result);
-int gg_chat_update(struct gg_session *sess, uint64_t id, uint32_t version,
- const uin_t *participants, unsigned int participants_count);
-gg_chat_list_t *gg_chat_find(struct gg_session *sess, uint64_t id);
-uin_t gg_str_to_uin(const char *str, int len);
-uint64_t gg_fix64(uint64_t x);
-void gg_connection_failure(struct gg_session *gs, struct gg_event *ge,
- enum gg_failure_t failure);
-time_t gg_server_time(struct gg_session *gs);
-int gg_session_init_ssl(struct gg_session *gs);
-void gg_close(struct gg_session *gs);
-struct gg_event *gg_eventqueue_add(struct gg_session *sess);
-void gg_compat_message_ack(struct gg_session *sess, int seq);
-void gg_image_sendout(struct gg_session *sess);
-void gg_strarr_free(char **strarr);
-char ** gg_strarr_dup(char **strarr);
-#define gg_win32_hook(orig_func, hook_func, data) \
- gg_win32_hook_f((void (*)())(orig_func), (void (*)())(hook_func), (data))
-gg_win32_hook_f(void (*orig_func)(), void (*hook_func)(), gg_win32_hook_data_t *data)
- 0x48, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, /* mov rax, uint64_t */
- 0xff, 0xe0 /* jmp rax */
- 0xB8, 0, 0, 0, 0, /* mov eax, uint32_t */
- 0xff, 0xe0 /* jmp eax */
- uint64_t addr = (uint64_t)hook_func;
- memcpy(&trap[2], &addr, sizeof(addr));
- uint32_t addr = (uint32_t)hook_func;
- memcpy(&trap[1], &addr, sizeof(addr));
- VirtualProtect(orig_func, sizeof(trap),
- PAGE_EXECUTE_READWRITE, &dPermission);
- memcpy(data->trap, trap, sizeof(trap));
- memcpy(data->original, orig_func, sizeof(trap));
- memcpy(orig_func, trap, sizeof(trap));
- VirtualProtect(orig_func, sizeof(trap),
- dPermission, &dPermission);
-gg_win32_hook_set_enabled(gg_win32_hook_data_t *data, int enabled)
- VirtualProtect(data->fnc, sizeof(data->trap),
- PAGE_EXECUTE_READWRITE, &dPermission);
- memcpy(data->fnc, src, sizeof(data->trap));
- VirtualProtect(data->fnc, sizeof(data->trap),
- dPermission, &dPermission);
-#endif /* LIBGADU_INTERNAL_H */
--- a/libpurple/protocols/gg/lib/libgadu.c Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,3082 +0,0 @@
- * (C) Copyright 2001-2010 Wojtek Kaniewski <wojtekka@irc.pl>
- * Robert J. Woźny <speedy@ziew.org>
- * Arkadiusz Miśkiewicz <arekm@pld-linux.org>
- * Tomasz Chiliński <chilek@chilan.com>
- * Adam Wysocki <gophi@ekg.chmurka.net>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
- * \brief Główny moduł biblioteki
-#include "packets.pb-c.h"
-#ifdef GG_CONFIG_HAVE_GNUTLS
-# include <gnutls/gnutls.h>
-#ifdef GG_CONFIG_HAVE_OPENSSL
-# include <openssl/err.h>
-# include <openssl/rand.h>
- * Port gniazda nasłuchującego dla połączeń bezpośrednich.
- * Adres IP gniazda nasłuchującego dla połączeń bezpośrednich.
-unsigned long gg_dcc_ip = 0;
- * Adres lokalnego interfejsu IP, z którego wywoływane są wszystkie połączenia.
-unsigned long gg_local_ip = 0;
- * Flaga włączenia połączeń przez serwer pośredniczący.
-int gg_proxy_enabled = 0;
- * Adres serwera pośredniczącego.
-char *gg_proxy_host = NULL;
- * Port serwera pośredniczącego.
- * Flaga używania serwera pośredniczącego jedynie dla usług HTTP.
-int gg_proxy_http_only = 0;
- * Nazwa użytkownika do autoryzacji serwera pośredniczącego.
-char *gg_proxy_username = NULL;
- * Hasło użytkownika do autoryzacji serwera pośredniczącego.
-char *gg_proxy_password = NULL;
-static char rcsid[] GG_UNUSED = "$Id$";
-static void gg_compat_message_sent(struct gg_session *sess, int seq, size_t recipients_count, uin_t *recipients);
-static void gg_compat_message_cleanup(struct gg_session *sess);
-#ifdef GG_CONFIG_IS_GPL_COMPLIANT
- * Symbol zdefiniowany tylko dla libgadu zgodnego z licencją GPL.
- * Zwracana wartość nie jest istotna, a ponadto może się zmienić w przyszłych
- * wersjach biblioteki. Istotne jest tylko wywołanie tej funkcji w kodzie, który
- * ma być zgodny z GPL, aby wymusić jej istnienie.
-int gg_is_gpl_compliant(void)
- * Zwraca wersję biblioteki.
- * \return Wskaźnik na statyczny bufor z wersją biblioteki.
-const char *gg_libgadu_version(void)
- return GG_LIBGADU_VERSION;
-void * gg_new0(size_t size)
- gg_debug(GG_DEBUG_MISC | GG_DEBUG_ERROR,
- "//gg_new0(%" GG_SIZE_FMT
- ") not enough memory\n", size);
-gg_required_proto(struct gg_session *gs, int protocol_version)
- if (gs->protocol_version >= protocol_version)
- gg_debug_session(gs, GG_DEBUG_MISC | GG_DEBUG_ERROR, "// requested "
- "feature requires protocol %#02x, but %#02x is selected\n",
- protocol_version, gs->protocol_version);
-int gg_get_dummy_fd(struct gg_session *sess)
- struct gg_session_private *p = sess->private_data;
- if (p->dummyfds_created)
- if (socketpair(AF_LOCAL, SOCK_STREAM, 0, p->dummyfds) == -1) {
- gg_debug(GG_DEBUG_MISC | GG_DEBUG_ERROR, "// gg_get_dummy_fd() "
- "unable to create pipes (errno=%d, %s)\n",
- errno, strerror(errno));
- p->dummyfds_created = 1;
- * \internal Liczy skrót z hasła i ziarna.
- * \param password Hasło
- * \param seed Ziarno podane przez serwer
- * \return Wartość skrótu
-unsigned int gg_login_hash(const unsigned char *password, unsigned int seed)
- for (x = 0; *password; password++) {
- x = (x & 0xffffff00) | *password;
- y = (y << z) | (y >> (32 - z));
- * \internal Odbiera od serwera dane binarne.
- * Funkcja odbiera dane od serwera zajmując się SSL/TLS w razie konieczności.
- * Obsługuje EINTR, więc użytkownik nie musi się przejmować przerwanymi
- * wywołaniami systemowymi.
- * \param sess Struktura sesji
- * \param buf Bufor na danymi
- * \param length Długość bufora
- * \return To samo co funkcja systemowa \c read
-int gg_read(struct gg_session *sess, char *buf, int length)
- struct gg_session_private *p = sess->private_data;
-#ifdef GG_CONFIG_HAVE_GNUTLS
- if (sess->ssl != NULL) {
- res = gnutls_record_recv(GG_SESSION_GNUTLS(sess), buf, length);
- if (res == GNUTLS_E_AGAIN)
- else if (!gnutls_error_is_fatal(res) || res == GNUTLS_E_INTERRUPTED)
-#ifdef GG_CONFIG_HAVE_OPENSSL
- if (sess->ssl != NULL) {
- res = SSL_read(sess->ssl, buf, length);
- err = SSL_get_error(sess->ssl, res);
- if (err == SSL_ERROR_SYSCALL && errno == EINTR)
- if (err == SSL_ERROR_WANT_READ)
- else if (err != SSL_ERROR_SYSCALL)
- if (p->socket_handle != NULL) {
- if (p->socket_manager.read_cb == NULL) {
- gg_debug_session(sess, GG_DEBUG_MISC | GG_DEBUG_ERROR,
- "// gg_read() socket_manager.read callback is "
- res = p->socket_manager.read_cb(
- p->socket_manager.cb_data, p->socket_handle,
- (unsigned char*)buf, length);
- } while (res < 0 && errno == EINTR);
- gg_debug_session(sess, GG_DEBUG_MISC | GG_DEBUG_ERROR,
- "// gg_read() unexpected errno=%d\n", errno);
- res = recv(sess->fd, buf, length, 0);
- if (res == -1 && errno == EINTR)
- * \internal Wysyła do serwera dane binarne.
- * Funkcja wysyła dane do serwera zajmując się SSL/TLS w razie konieczności.
- * Obsługuje EINTR, więc użytkownik nie musi się przejmować przerwanymi
- * wywołaniami systemowymi.
- * \note Funkcja nie zajmuje się buforowaniem wysyłanych danych (patrz
- * \param sess Struktura sesji
- * \param buf Bufor z danymi
- * \param length Długość bufora
- * \return To samo co funkcja systemowa \c write
-static int gg_write_common(struct gg_session *sess, const char *buf, int length)
- struct gg_session_private *p = sess->private_data;
-#ifdef GG_CONFIG_HAVE_GNUTLS
- if (sess->ssl != NULL) {
- res = gnutls_record_send(GG_SESSION_GNUTLS(sess), buf, length);
- if (!gnutls_error_is_fatal(res) || res == GNUTLS_E_INTERRUPTED)
- if (res == GNUTLS_E_AGAIN)
-#ifdef GG_CONFIG_HAVE_OPENSSL
- if (sess->ssl != NULL) {
- res = SSL_write(sess->ssl, buf, length);
- err = SSL_get_error(sess->ssl, res);
- if (err == SSL_ERROR_SYSCALL && errno == EINTR)
- if (err == SSL_ERROR_WANT_WRITE)
- else if (err != SSL_ERROR_SYSCALL)
- if (p->socket_handle != NULL) {
- if (p->socket_manager.write_cb == NULL) {
- gg_debug_session(sess, GG_DEBUG_MISC | GG_DEBUG_ERROR,
- "// gg_write_common() socket_manager.write "
- "callback is empty\n");
- res = p->socket_manager.write_cb(
- p->socket_manager.cb_data, p->socket_handle,
- (const unsigned char*)buf, length);
- } while (res < 0 && errno == EINTR);
- gg_debug_session(sess, GG_DEBUG_MISC | GG_DEBUG_ERROR,
- "// gg_read() unexpected errno=%d\n", errno);
- res = send(sess->fd, buf, length, 0);
- if (res == -1 && errno == EINTR)
- * \internal Wysyła do serwera dane binarne.
- * Funkcja wysyła dane do serwera zajmując się TLS w razie konieczności.
- * \param sess Struktura sesji
- * \param buf Bufor z danymi
- * \param length Długość bufora
- * \return To samo co funkcja systemowa \c write
-int gg_write(struct gg_session *sess, const char *buf, int length)
- while (written < length) {
- res = gg_write_common(sess, buf + written, length - written);
- if (sess->send_buf == NULL) {
- res = gg_write_common(sess, buf, length);
- if (res == -1 && errno == EAGAIN)
- if (!(tmp = realloc(sess->send_buf, sess->send_left + length - res))) {
- memcpy(sess->send_buf + sess->send_left, buf + res, length - res);
- sess->send_left += length - res;
-void gg_close(struct gg_session *sess)
- struct gg_session_private *p = sess->private_data;
- if (!p->socket_is_external) {
- assert(p->socket_manager_type !=
- GG_SOCKET_MANAGER_TYPE_INTERNAL);
- if (p->socket_handle != NULL) {
- p->socket_manager.close_cb(p->socket_manager.cb_data,
- p->socket_is_external = 0;
- p->socket_handle = NULL;
- while (p->event_queue) {
- gg_eventqueue_t *next = p->event_queue->next;
- gg_event_free(p->event_queue->event);
- while (p->imgout_queue) {
- gg_imgout_queue_t *next = p->imgout_queue->next;
- p->imgout_queue = next;
- if (p->dummyfds_created) {
- p->dummyfds_created = 0;
- gg_compat_message_cleanup(sess);
- * \internal Odbiera pakiet od serwera.
- * Funkcja odczytuje nagłówek pakietu, a następnie jego zawartość i zwraca
- * w zaalokowanym buforze.
- * Przy połączeniach asynchronicznych, funkcja może nie być w stanie
- * skompletować całego pakietu -- w takim przypadku zwróci \c NULL, a kodem błędu
- * \param sess Struktura sesji
- * \return Wskaźnik do zaalokowanego bufora
-void *gg_recv_packet(struct gg_session *sess)
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_recv_packet(%p);\n", sess);
- if (sess->recv_buf == NULL && sess->recv_done == 0) {
- sess->recv_buf = malloc(sizeof(struct gg_header) + 1);
- if (sess->recv_buf == NULL) {
- gg_debug_session(sess, GG_DEBUG_ERROR, "// gg_recv_packet() out of memory\n");
- gh = (struct gg_header*) sess->recv_buf;
- if ((size_t) sess->recv_done < sizeof(struct gg_header)) {
- len = sizeof(struct gg_header) - sess->recv_done;
- gg_debug_session(sess, GG_DEBUG_NET,
- "// gg_recv_packet() header: %d done, "
- "%" GG_SIZE_FMT " to go\n",
- ghlen = gh ? gg_fix32(gh->length) : 0;
- gg_debug_session(sess, GG_DEBUG_ERROR,
- "// gg_recv_packet() invalid packet "
- "length (%d)\n", ghlen);
- if ((size_t) sess->recv_done >= sizeof(struct gg_header) + ghlen) {
- gg_debug_session(sess, GG_DEBUG_NET, "// gg_recv_packet() and that's it\n");
- len = sizeof(struct gg_header) + ghlen - sess->recv_done;
- gg_debug_session(sess, GG_DEBUG_NET,
- "// gg_recv_packet() payload: %d done, "
- "%u length, %" GG_SIZE_FMT " to go\n",
- sess->recv_done, ghlen, len);
- res = gg_read(sess, sess->recv_buf + sess->recv_done, len);
- gg_debug_session(sess, GG_DEBUG_ERROR, "// gg_recv_packet() connection broken\n");
- if (res == -1 && errno == EAGAIN) {
- gg_debug_session(sess, GG_DEBUG_NET, "// gg_recv_packet() resource temporarily unavailable\n");
- gg_debug_session(sess, GG_DEBUG_ERROR,
- "// gg_recv_packet() read failed: errno=%d, "
- "%s\n", errno, strerror(errno));
- gg_debug_session(sess, GG_DEBUG_NET, "// gg_recv_packet() read %d bytes\n", res);
- if (sess->recv_done + res == sizeof(struct gg_header)) {
- ghlen = gh ? gg_fix32(gh->length) : 0;
- gg_debug_session(sess, GG_DEBUG_NET,
- "// gg_recv_packet() header complete, "
- "payload %d bytes\n", ghlen);
- gg_debug_session(sess, GG_DEBUG_ERROR,
- "// gg_recv_packet() invalid packet "
- "length (%d)\n", ghlen);
- tmp = realloc(sess->recv_buf, sizeof(struct gg_header) + ghlen + 1);
- gg_debug_session(sess, GG_DEBUG_ERROR, "// gg_recv_packet() out of memory\n");
- sess->recv_done += res;
- packet = sess->recv_buf;
- /* Czasami zakładamy, że teksty w pakietach są zakończone zerem */
- packet[sizeof(struct gg_header) + ghlen] = 0;
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet(type=0x%.2x, "
- "length=%d)\n", gg_fix32(gh->type), ghlen);
- gg_debug_dump(sess, GG_DEBUG_DUMP, packet, sizeof(struct gg_header) + ghlen);
- gh->type = gg_fix32(gh->type);
- * \internal Wysyła pakiet do serwera.
- * Funkcja konstruuje pakiet do wysłania z dowolnej liczby fragmentów. Jeśli
- * rozmiar pakietu jest za duży, by móc go wysłać za jednym razem, pozostała
- * część zostanie zakolejkowana i wysłana, gdy będzie to możliwe.
- * \param sess Struktura sesji
- * \param type Rodzaj pakietu
- * \param ... Lista kolejnych części pakietu (wskaźnik na bufor i długość
- * typu \c int) zakończona \c NULL
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_send_packet(struct gg_session *sess, int type, ...)
- unsigned int tmp_length;
- unsigned int payload_length;
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_packet(%p, 0x%.2x, ...);\n", sess, type);
- tmp_length = sizeof(struct gg_header);
- if (!(tmp = malloc(tmp_length))) {
- gg_debug_session(sess, GG_DEBUG_ERROR, "// gg_send_packet() not enough memory for packet header\n");
- payload = va_arg(ap, void *);
- payload_length = va_arg(ap, unsigned int);
- if (!(tmp2 = realloc(tmp, tmp_length + payload_length))) {
- gg_debug_session(sess, GG_DEBUG_ERROR, "// gg_send_packet() not enough memory for payload\n");
- memcpy(tmp + tmp_length, payload, payload_length);
- tmp_length += payload_length;
- payload = va_arg(ap, void *);
- h = (struct gg_header*) tmp;
- h->type = gg_fix32(type);
- h->length = gg_fix32(tmp_length - sizeof(struct gg_header));
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_send_packet(type=0x%.2x, "
- "length=%d)\n", gg_fix32(h->type), gg_fix32(h->length));
- gg_debug_dump(sess, GG_DEBUG_DUMP, tmp, tmp_length);
- res = gg_write(sess, tmp, tmp_length);
- gg_debug_session(sess, GG_DEBUG_ERROR, "// gg_send_packet() "
- "write() failed. res = %d, errno = %d (%s)\n",
- res, errno, strerror(errno));
- gg_debug_session(sess, GG_DEBUG_NET, "// gg_send_packet() "
- "partial write(), %d sent, %d left, %d total left\n",
- res, tmp_length - res, sess->send_left);
- sess->check |= GG_CHECK_WRITE;
- * \internal Funkcja zwrotna sesji.
- * Pole \c callback struktury \c gg_session zawiera wskaźnik do tej funkcji.
- * Wywołuje ona \c gg_watch_fd i zachowuje wynik w polu \c event.
- * \note Korzystanie z tej funkcjonalności nie jest już zalecane.
- * \param sess Struktura sesji
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-static int gg_session_callback(struct gg_session *sess)
- return ((sess->event = gg_watch_fd(sess)) != NULL) ? 0 : -1;
- * Łączy się z serwerem Gadu-Gadu.
- * Przy połączeniu synchronicznym funkcja zakończy działanie po nawiązaniu
- * połączenia lub gdy wystąpi błąd. Po udanym połączeniu należy wywoływać
- * funkcję \c gg_watch_fd(), która odbiera informacje od serwera i zwraca
- * informacje o zdarzeniach.
- * Przy połączeniu asynchronicznym funkcja rozpocznie procedurę połączenia
- * i zwróci zaalokowaną strukturę. Pole \c fd struktury \c gg_session zawiera
- * deskryptor, który należy obserwować funkcją \c select, \c poll lub za
- * pomocą mechanizmów użytej pętli zdarzeń (Glib, Qt itp.). Pole \c check
- * jest maską bitową mówiącą, czy biblioteka chce być informowana o możliwości
- * odczytu danych (\c GG_CHECK_READ) czy zapisu danych (\c GG_CHECK_WRITE).
- * Po zaobserwowaniu zmian na deskryptorze należy wywołać funkcję
- * \c gg_watch_fd(). Podczas korzystania z połączeń asynchronicznych, w trakcie
- * połączenia może zostać stworzony dodatkowy proces rozwiązujący nazwę
- * serwera -- z tego powodu program musi poprawnie obsłużyć sygnał SIGCHLD.
- * \note Po nawiązaniu połączenia z serwerem należy wysłać listę kontaktów
- * za pomocą funkcji \c gg_notify() lub \c gg_notify_ex().
- * \note Funkcja zwróci błąd ENOSYS jeśli połączenie SSL było wymagane, ale
- * obsługa SSL nie jest wkompilowana.
- * \param p Struktura opisująca parametry połączenia. Wymagane pola: uin,
- * \return Wskaźnik do zaalokowanej struktury sesji \c gg_session lub NULL
-struct gg_session *gg_login(const struct gg_login_params *p)
- struct gg_session *sess = NULL;
- struct gg_session_private *sess_private = NULL;
- gg_debug(GG_DEBUG_FUNCTION, "** gg_login(%p);\n", p);
- gg_debug(GG_DEBUG_FUNCTION, "** gg_login(%p: [uin=%u, async=%d, ...]);\n", p, p->uin, p->async);
- sess = malloc(sizeof(struct gg_session));
- gg_debug(GG_DEBUG_MISC, "// gg_login() not enough memory for session data\n");
- memset(sess, 0, sizeof(struct gg_session));
- sess_private = malloc(sizeof(struct gg_session_private));
- if (sess_private == NULL) {
- gg_debug(GG_DEBUG_MISC, "// gg_login() not enough memory for session private data\n");
- memset(sess_private, 0, sizeof(struct gg_session_private));
- sess->private_data = sess_private;
- if (p->password == NULL || p->uin == 0) {
- gg_debug(GG_DEBUG_MISC, "// gg_login() invalid arguments. uin and password needed\n");
- if (!(sess->password = strdup(p->password))) {
- gg_debug(GG_DEBUG_MISC, "// gg_login() not enough memory for password\n");
- if (p->hash_type < 0 || p->hash_type > GG_LOGIN_HASH_SHA1) {
- gg_debug(GG_DEBUG_MISC, "// gg_login() invalid arguments. unknown hash type (%d)\n", p->hash_type);
- sess->state = GG_STATE_RESOLVING;
- sess->check = GG_CHECK_READ;
- sess->timeout = GG_DEFAULT_TIMEOUT;
- sess->async = p->async;
- sess->type = GG_SESSION_GG;
- sess->initial_status = p->status;
- sess->callback = gg_session_callback;
- sess->destroy = gg_free_session;
- sess->port = p->server_port;
- sess->server_addr = p->server_addr;
- sess->external_port = p->external_port;
- sess->external_addr = p->external_addr;
- sess->client_addr = p->client_addr;
- sess->client_port = p->client_port;
- if (GG_LOGIN_PARAMS_HAS_FIELD(p, compatibility))
- sess_private->compatibility = p->compatibility;
- if (GG_LOGIN_PARAMS_HAS_FIELD(p, connect_host) && p->connect_host != NULL) {
- sess->connect_host = strdup(p->connect_host);
- if (sess->connect_host == NULL)
- colon = strchr(sess->connect_host, ':');
- port = atoi(colon + 1);
- if (GG_LOGIN_PARAMS_HAS_FIELD(p, socket_manager_type) &&
- GG_LOGIN_PARAMS_HAS_FIELD(p, socket_manager) &&
- p->socket_manager_type != GG_SOCKET_MANAGER_TYPE_INTERNAL)
- if ((unsigned int)p->socket_manager_type >
- GG_SOCKET_MANAGER_TYPE_TLS)
- gg_debug(GG_DEBUG_MISC | GG_DEBUG_ERROR, "// gg_login()"
- " invalid arguments. unknown socket manager "
- "type (%d)\n", p->socket_manager_type);
- sess_private->socket_manager_type =
- p->socket_manager_type;
- memcpy(&sess_private->socket_manager,
- sizeof(gg_socket_manager_t));
- sess_private->socket_manager_type =
- GG_SOCKET_MANAGER_TYPE_INTERNAL;
- if (GG_LOGIN_PARAMS_HAS_FIELD(p, host_white_list) &&
- p->host_white_list != NULL)
- sess_private->host_white_list =
- gg_strarr_dup(p->host_white_list);
- if (sess_private->host_white_list == NULL)
- if (p->protocol_features == 0) {
- sess->protocol_features = GG_FEATURE_MSG80 |
- GG_FEATURE_STATUS80 | GG_FEATURE_DND_FFC |
- GG_FEATURE_IMAGE_DESCR | GG_FEATURE_UNKNOWN_100 |
- GG_FEATURE_USER_DATA | GG_FEATURE_MSG_ACK |
- GG_FEATURE_TYPING_NOTIFICATION;
- sess->protocol_features = (p->protocol_features & ~(GG_FEATURE_STATUS77 | GG_FEATURE_MSG77));
- if (!(p->protocol_features & GG_FEATURE_STATUS77))
- sess->protocol_features |= GG_FEATURE_STATUS80;
- if (!(p->protocol_features & GG_FEATURE_MSG77))
- sess->protocol_features |= GG_FEATURE_MSG80;
- if (!(sess->status_flags = p->status_flags))
- sess->status_flags = GG_STATUS_FLAG_UNKNOWN | GG_STATUS_FLAG_SPAM;
- if (!p->protocol_version)
- sess->protocol_version = GG_DEFAULT_PROTOCOL_VERSION;
- else if (p->protocol_version < 0x2e) {
- gg_debug(GG_DEBUG_MISC, "// gg_login() libgadu no longer support protocol < 0x2e\n");
- sess->protocol_version = 0x2e;
- sess->protocol_version = p->protocol_version;
- if (p->client_version && strcmp(p->client_version, "-") != 0)
- sess->client_version = strdup(p->client_version);
- sess->last_sysmsg = p->last_sysmsg;
- sess->image_size = p->image_size;
- sess->encoding = p->encoding;
- if (gg_session_set_resolver(sess, p->resolver) == -1) {
- gg_debug(GG_DEBUG_MISC, "// gg_login() invalid arguments. "
- "unsupported resolver type (%d)\n", p->resolver);
- sess->initial_descr = gg_encoding_convert(p->status_descr, p->encoding, GG_ENCODING_UTF8, -1, -1);
- if (!sess->initial_descr) {
- gg_debug(GG_DEBUG_MISC, "// gg_login() not enough memory for status\n");
- /* XXX pamiętać, żeby nie ciąć w środku znaku utf-8 */
- if (strlen(sess->initial_descr) > GG_STATUS_DESCR_MAXSIZE)
- sess->initial_descr[GG_STATUS_DESCR_MAXSIZE] = 0;
- if (p->tls != GG_SSL_DISABLED) {
-#if !defined(GG_CONFIG_HAVE_GNUTLS) && !defined(GG_CONFIG_HAVE_OPENSSL)
- gg_debug(GG_DEBUG_MISC, "// gg_login() client requested TLS but no support compiled in\n");
- if (p->tls == GG_SSL_REQUIRED) {
- sess->ssl_flag = p->tls;
- sess->hash_type = p->hash_type;
- sess->hash_type = GG_LOGIN_HASH_SHA1;
- if (sess->server_addr == 0 && sess->connect_host == NULL) {
- if (gg_proxy_enabled) {
- sess->resolver_host = gg_proxy_host;
- sess->proxy_port = gg_proxy_port;
- sess->state = (sess->async) ?
- GG_STATE_RESOLVE_PROXY_HUB_ASYNC :
- GG_STATE_RESOLVE_PROXY_HUB_SYNC;
- sess->resolver_host = GG_APPMSG_HOST;
- sess->state = (sess->async) ? GG_STATE_RESOLVE_HUB_ASYNC : GG_STATE_RESOLVE_HUB_SYNC;
- if (sess->connect_host != NULL)
- /* XXX inet_ntoa i wielowątkowość */
- sess->connect_host = strdup(inet_ntoa(*(struct in_addr*) &sess->server_addr));
- if (sess->connect_host == NULL)
- sess->connect_index = 0;
- if (gg_proxy_enabled) {
- sess->resolver_host = gg_proxy_host;
- sess->proxy_port = gg_proxy_port;
- sess->connect_port[0] = GG_HTTPS_PORT;
- sess->connect_port[0] = sess->port;
- sess->connect_port[1] = 0;
- sess->state = (sess->async) ? GG_STATE_RESOLVE_PROXY_GG_ASYNC : GG_STATE_RESOLVE_PROXY_GG_SYNC;
- sess->resolver_host = sess->connect_host;
- if (sess->ssl_flag == GG_SSL_DISABLED) {
- sess->connect_port[0] = GG_DEFAULT_PORT;
- sess->connect_port[1] = GG_HTTPS_PORT;
- sess->connect_port[0] = GG_HTTPS_PORT;
- sess->connect_port[1] = 0;
- sess->connect_port[0] = sess->port;
- sess->connect_port[1] = 0;
- sess->state = (sess->async) ? GG_STATE_RESOLVE_GG_ASYNC : GG_STATE_RESOLVE_GG_SYNC;
- /* XXX inaczej gg_watch_fd() wyjdzie z timeoutem */
- sess->timeout = GG_DEFAULT_TIMEOUT;
- while (!GG_SESSION_IS_CONNECTED(sess)) {
- ge = gg_watch_fd(sess);
- gg_debug(GG_DEBUG_MISC, "// gg_session_connect() critical error in gg_watch_fd()\n");
- if (ge->type == GG_EVENT_CONN_FAILED) {
- gg_debug(GG_DEBUG_MISC, "// gg_session_connect() could not login\n");
- ge = gg_watch_fd(sess);
- gg_debug(GG_DEBUG_MISC, "// gg_session_connect() critical error in gg_watch_fd()\n");
- * Wysyła do serwera pakiet utrzymania połączenia.
- * Klient powinien regularnie co minutę wysyłać pakiet utrzymania połączenia,
- * inaczej serwer uzna, że klient stracił łączność z siecią i zerwie
- * \param sess Struktura sesji
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_ping(struct gg_session *sess)
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_ping(%p);\n", sess);
- if (sess->state != GG_STATE_CONNECTED) {
- return gg_send_packet(sess, GG_PING, NULL);
- * Kończy połączenie z serwerem.
- * Funkcja nie zwalnia zasobów, więc po jej wywołaniu należy użyć
- * \c gg_free_session(). Jeśli chce się ustawić opis niedostępności, należy
- * wcześniej wywołać funkcję \c gg_change_status_descr() lub
- * \c gg_change_status_descr_time().
- * \note Jeśli w buforze nadawczym połączenia z serwerem znajdują się jeszcze
- * dane (np. z powodu strat pakietów na łączu), prawdopodobnie zostaną one
- * utracone przy zrywaniu połączenia. Aby mieć pewność, że opis statusu
- * zostanie zachowany, należy ustawić stan \c GG_STATUS_NOT_AVAIL_DESCR
- * za pomocą funkcji \c gg_change_status_descr() i poczekać na zdarzenie
- * \c GG_EVENT_DISCONNECT_ACK.
- * \param sess Struktura sesji
-void gg_logoff(struct gg_session *sess)
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_logoff(%p);\n", sess);
-#ifdef GG_CONFIG_HAVE_GNUTLS
- gnutls_bye(GG_SESSION_GNUTLS(sess), GNUTLS_SHUT_RDWR);
-#ifdef GG_CONFIG_HAVE_OPENSSL
- SSL_shutdown(sess->ssl);
- sess->resolver_cleanup(&sess->resolver, 1);
- * Zwalnia zasoby używane przez połączenie z serwerem. Funkcję należy wywołać
- * po zamknięciu połączenia z serwerem, by nie doprowadzić do wycieku zasobów
- * \param sess Struktura sesji
-void gg_free_session(struct gg_session *sess)
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_free_session(%p);\n", sess);
- /* XXX dopisać zwalnianie i zamykanie wszystkiego, co mogło zostać */
- free(sess->resolver_result);
- free(sess->connect_host);
- free(sess->initial_descr);
- free(sess->client_version);
- free(sess->header_buf);
-#ifdef GG_CONFIG_HAVE_GNUTLS
- if (sess->ssl != NULL) {
- gg_session_gnutls_t *tmp;
- tmp = (gg_session_gnutls_t*) sess->ssl;
- gnutls_deinit(tmp->session);
- gnutls_certificate_free_credentials(tmp->xcred);
- gnutls_global_deinit();
-#ifdef GG_CONFIG_HAVE_OPENSSL
- SSL_CTX_free(sess->ssl_ctx);
- if (sess->resolver_cleanup != NULL)
- sess->resolver_cleanup(&sess->resolver, 1);
- struct gg_image_queue *next = sess->images->next;
- gg_image_queue_remove(sess, sess->images, 1);
- /* a fix for false-positive NULL-dereference */
- for (dcc = sess->dcc7_list; dcc; dcc = dcc->next)
- chat = sess->private_data->chat_list;
- gg_chat_list_t *next = chat->next;
- free(chat->participants);
- gg_strarr_free(sess->private_data->host_white_list);
- free(sess->private_data);
- * Zmienia status użytkownika.
- * \param sess Struktura sesji
- * \param status Nowy status użytkownika
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_change_status(struct gg_session *sess, int status)
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_change_status(%p, %d);\n", sess, status);
- return gg_change_status_descr(sess, status, NULL);
- * Zmienia status użytkownika na status opisowy.
- * \param sess Struktura sesji
- * \param status Nowy status użytkownika
- * \param descr Opis statusu użytkownika (lub \c NULL)
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_change_status_descr(struct gg_session *sess, int status, const char *descr)
- struct gg_new_status80 p;
- char *gen_descr = NULL;
- int descr_null_len = 0;
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_change_status_descr(%p, %d, \"%s\");\n", sess, status, descr);
- if (sess->state != GG_STATE_CONNECTED) {
- if (descr != NULL && sess->encoding != GG_ENCODING_UTF8) {
- descr = gen_descr = gg_encoding_convert(descr, GG_ENCODING_CP1250, GG_ENCODING_UTF8, -1, -1);
- descr_len = strlen(descr);
- if (descr_len > GG_STATUS_DESCR_MAXSIZE)
- descr_len = GG_STATUS_DESCR_MAXSIZE;
- /* XXX pamiętać o tym, żeby nie ucinać w środku znaku utf-8 */
- p.status = gg_fix32(status);
- p.flags = gg_fix32(sess->status_flags);
- p.description_size = gg_fix32(descr_len);
- if (sess->protocol_version >= GG_PROTOCOL_VERSION_110) {
- p.flags = gg_fix32(0x00000014);
- res = gg_send_packet(sess, GG_NEW_STATUS80,
- &p, sizeof(p), descr, descr_len,
- "\x00", descr_null_len, NULL);
- sess->state = GG_STATE_DISCONNECTING;
- sess->timeout = GG_TIMEOUT_DISCONNECT;
- * Zmienia status użytkownika na status opisowy z podanym czasem powrotu.
- * \param sess Struktura sesji
- * \param status Nowy status użytkownika
- * \param descr Opis statusu użytkownika
- * \param ts Czas powrotu w postaci uniksowego znacznika czasu
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_change_status_descr_time(struct gg_session *sess, int status, const char *descr, int ts)
- gg_debug_session(sess, GG_DEBUG_FUNCTION,
- "** gg_change_status_descr_time(%p, %d, \"%s\", %d);\n",
- sess, status, descr, ts);
- return gg_change_status_descr(sess, status, descr);
- * Funkcja zmieniająca flagi statusu.
- * \param sess Struktura sesji
- * \param flags Nowe flagi statusu
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
- * \note Aby zmiany weszły w życie, należy ponownie ustawić status za pomocą
- * funkcji z rodziny \c gg_change_status().
-int gg_change_status_flags(struct gg_session *sess, int flags)
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_change_status_flags(%p, 0x%08x);\n", sess, flags);
- sess->status_flags = flags;
-static int gg_send_message_110(struct gg_session *sess,
- uin_t recipient, uint64_t chat_id,
- const char *message, int is_html)
- GG110SendMessage msg = GG110_SEND_MESSAGE__INIT;
- int packet_type = recipient ? GG_SEND_MSG110 : GG_CHAT_SEND_MSG;
- char *html_message_gen = NULL, *plain_message_gen = NULL;
- const char *html_message, *plain_message;
- gg_debug_session(sess, GG_DEBUG_FUNCTION,
- "** gg_send_message_110(%p, %u, %" PRIu64 ", %p, %d);\n",
- sess, recipient, chat_id, message, is_html);
- if ((recipient == 0) == (chat_id == 0))
- html_message = message;
- if (sess->encoding != GG_ENCODING_UTF8) {
- html_message = html_message_gen = gg_encoding_convert(
- html_message, sess->encoding, GG_ENCODING_UTF8,
- if (html_message_gen == NULL)
- plain_message = plain_message_gen =
- gg_message_html_to_text_110(html_message);
- if (plain_message_gen == NULL) {
- free(html_message_gen);
- plain_message = message;
- if (sess->encoding != GG_ENCODING_UTF8) {
- plain_message = plain_message_gen = gg_encoding_convert(
- plain_message, sess->encoding, GG_ENCODING_UTF8,
- if (plain_message_gen == NULL)
- html_message = html_message_gen =
- gg_message_text_to_html_110(plain_message, -1);
- if (html_message_gen == NULL) {
- free(plain_message_gen);
- gg_protobuf_set_uin(&msg.recipient, recipient, NULL);
- /* rzutujemy z const, ale msg i tak nie będzie modyfikowany */
- msg.msg_plain = (char*)plain_message;
- msg.msg_xhtml = (char*)html_message;
- if (!GG_PROTOBUF_SEND(sess, NULL, packet_type, gg110_send_message, msg))
- free(html_message_gen);
- free(plain_message_gen);
- return succ ? seq : -1;
-gg_message_legacy_text_to_html(const char *src, gg_encoding_t encoding,
- const unsigned char *format, size_t format_len)
- if (format == NULL || format_len <= 3) {
- len = gg_message_text_to_html(NULL, src, encoding, format, format_len);
- gg_message_text_to_html(dst, src, encoding, format, format_len);
- * \internal Wysyła wiadomość.
- * Zwraca losowy numer sekwencyjny, który można zignorować albo wykorzystać
- * \param sess Struktura sesji
- * \param msgclass Klasa wiadomości
- * \param recipients_count Liczba adresatów
- * \param recipients Wskaźnik do tablicy z numerami adresatów
- * \param message Treść wiadomości
- * \param format Informacje o formatowaniu
- * \param formatlen Długość informacji o formatowaniu
- * \param html_message Treść wiadomości HTML
- * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu.
-static int gg_send_message_common(struct gg_session *sess, int msgclass,
- int recipients_count, uin_t *recipients, const unsigned char *message,
- const unsigned char *format, int formatlen,
- const unsigned char *html_message)
- struct gg_send_msg80 s80;
- const char *cp_msg = NULL, *utf_html_msg = NULL;
- char *recoded_msg = NULL, *recoded_html_msg = NULL;
- unsigned char *generated_format = NULL;
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message_common("
- "%p, %d, %d, %p, %p, %p, %d, %p);\n", sess, msgclass,
- recipients_count, recipients, message, format,
- formatlen, html_message);
- if (sess->state != GG_STATE_CONNECTED) {
- if ((message == NULL && html_message == NULL) ||
- recipients_count <= 0 || recipients_count > 0xffff ||
- recipients == NULL || (format == NULL && formatlen != 0))
- if (sess->protocol_version >= GG_PROTOCOL_VERSION_110 &&
- int is_html = (html_message != NULL);
- char *formatted_msg = NULL;
- if (formatlen > 3 && !is_html) {
- gg_debug_session(sess, GG_DEBUG_MISC | GG_DEBUG_WARNING,
- "// gg_send_message_common() using legacy "
- "formatting with new protocol\n");
- formatted_msg = gg_message_legacy_text_to_html(
- (const char *)message, sess->encoding,
- if (formatted_msg == NULL)
- html_message = (unsigned char*)formatted_msg;
- seq_no = gg_send_message_110(sess, recipients[0], 0,
- (const char*)(is_html ? html_message : message),
- if (sess->protocol_version >= GG_PROTOCOL_VERSION_110 &&
- !gg_compat_feature_is_enabled(sess, GG_COMPAT_FEATURE_LEGACY_CONFER))
- gg_debug_session(sess, GG_DEBUG_MISC | GG_DEBUG_ERROR,
- "// gg_send_message_common() legacy conferences disabled\n");
- uint16_t fixed_fmt_len;
- len = gg_message_html_to_text(NULL, NULL, &fmt_len, (const char*) html_message, sess->encoding);
- tmp_msg = malloc(len + 1);
- generated_format = malloc(fmt_len + 3);
- if (generated_format == NULL) {
- generated_format[0] = '\x02';
- fixed_fmt_len = gg_fix16(fmt_len);
- memcpy(generated_format + 1, &fixed_fmt_len, sizeof(fixed_fmt_len));
- gg_message_html_to_text(tmp_msg, generated_format + 3,
- NULL, (const char*)html_message, sess->encoding);
- format = generated_format;
- formatlen = fmt_len + 3;
- gg_message_html_to_text(tmp_msg, NULL, NULL, (const char*) html_message, sess->encoding);
- if (sess->encoding != GG_ENCODING_CP1250) {
- cp_msg = recoded_msg = gg_encoding_convert(tmp_msg, sess->encoding, GG_ENCODING_CP1250, -1, -1);
- cp_msg = recoded_msg = tmp_msg;
- if (sess->encoding != GG_ENCODING_CP1250) {
- cp_msg = recoded_msg = gg_encoding_convert(
- (const char*)message, sess->encoding,
- GG_ENCODING_CP1250, -1, -1);
- cp_msg = (const char*) message;
- if (html_message == NULL) {
- formatted_msg = gg_message_legacy_text_to_html(
- (const char*)message, sess->encoding, format, formatlen);
- if (formatted_msg == NULL)
- if (sess->encoding == GG_ENCODING_UTF8) {
- utf_html_msg = recoded_html_msg = formatted_msg;
- utf_html_msg = recoded_html_msg = gg_encoding_convert(
- formatted_msg, sess->encoding,
- GG_ENCODING_UTF8, -1, -1);
- if (utf_html_msg == NULL)
- if (sess->encoding == GG_ENCODING_UTF8) {
- utf_html_msg = (const char*) html_message;
- utf_html_msg = recoded_html_msg = gg_encoding_convert(
- (const char*)html_message, sess->encoding,
- GG_ENCODING_UTF8, -1, -1);
- if (utf_html_msg == NULL)
- /* Drobne odchylenie od protokołu. Jeśli wysyłamy kilka
- * wiadomości w ciągu jednej sekundy, zwiększamy poprzednią
- * wartość, żeby każda wiadomość miała unikalny numer.
- if (seq_no <= sess->seq)
- seq_no = sess->seq + 1;
- s80.seq = gg_fix32(seq_no);
- s80.msgclass = gg_fix32(msgclass);
- s80.offset_plain = gg_fix32(sizeof(s80) + strlen(utf_html_msg) + 1);
- s80.offset_attr = gg_fix32(sizeof(s80) + strlen(utf_html_msg) + 1 + strlen(cp_msg) + 1);
- if (recipients_count > 1) {
- struct gg_msg_recipients r;
- r.flag = GG_MSG_OPTION_CONFERENCE;
- r.count = gg_fix32(recipients_count - 1);
- recps = malloc(sizeof(uin_t) * (recipients_count - 1));
- for (i = 0; i < recipients_count; i++) {
- for (j = 0, k = 0; j < recipients_count; j++) {
- recps[k] = gg_fix32(recipients[j]);
- s80.recipient = gg_fix32(recipients[i]);
- if (gg_send_packet(sess, GG_SEND_MSG80, &s80,
- sizeof(s80), utf_html_msg,
- strlen(utf_html_msg) + 1, cp_msg,
- strlen(cp_msg) + 1, &r, sizeof(r), recps,
- (recipients_count - 1) * sizeof(uin_t), format,
- formatlen, NULL) == -1)
- s80.recipient = gg_fix32(recipients[0]);
- if (gg_send_packet(sess, GG_SEND_MSG80, &s80, sizeof(s80),
- utf_html_msg, strlen(utf_html_msg) + 1, cp_msg,
- strlen(cp_msg) + 1, format, formatlen, NULL) == -1)
- free(recoded_html_msg);
- free(generated_format);
- gg_compat_message_sent(sess, seq_no, recipients_count, recipients);
- * Wysyła wiadomość do użytkownika.
- * Zwraca losowy numer sekwencyjny, który można zignorować albo wykorzystać
- * \param sess Struktura sesji
- * \param msgclass Klasa wiadomości
- * \param recipient Numer adresata
- * \param message Treść wiadomości
- * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu.
-int gg_send_message(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message)
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message(%p, %d, "
- "%u, %p)\n", sess, msgclass, recipient, message);
- if (sess->protocol_version >= GG_PROTOCOL_VERSION_110) {
- seq_no = gg_send_message_110(sess, recipient, 0, (const char*)message, 0);
- gg_compat_message_sent(sess, seq_no, 1, &recipient);
- return gg_send_message_common(sess, msgclass, 1, &recipient, message,
- (const unsigned char*)"\x02\x06\x00\x00\x00\x08\x00\x00\x00",
- * Wysyła wiadomość formatowaną.
- * Zwraca losowy numer sekwencyjny, który można zignorować albo wykorzystać
- * \param sess Struktura sesji
- * \param msgclass Klasa wiadomości
- * \param recipient Numer adresata
- * \param message Treść wiadomości
- * \param format Informacje o formatowaniu
- * \param formatlen Długość informacji o formatowaniu
- * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu.
-int gg_send_message_richtext(struct gg_session *sess, int msgclass,
- uin_t recipient, const unsigned char *message,
- const unsigned char *format, int formatlen)
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message_richtext("
- "%p, %d, %u, %p, %p, %d);\n", sess, msgclass, recipient,
- message, format, formatlen);
- return gg_send_message_common(sess, msgclass, 1, &recipient, message, format, formatlen, NULL);
- * Wysyła formatowaną wiadomość HTML.
- * Zwraca losowy numer sekwencyjny, który można zignorować albo wykorzystać
- * \param sess Struktura sesji
- * \param msgclass Klasa wiadomości
- * \param recipient Numer adresata
- * \param html_message Treść wiadomości HTML
- * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu.
-int gg_send_message_html(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *html_message)
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message_html(%p, "
- "%d, %u, %p);\n", sess, msgclass, recipient, html_message);
- return gg_send_message_common(sess, msgclass, 1, &recipient, NULL, NULL, 0, html_message);
- * Wysyła wiadomość w ramach konferencji.
- * Zwraca losowy numer sekwencyjny, który można zignorować albo wykorzystać
- * \param sess Struktura sesji
- * \param msgclass Klasa wiadomości
- * \param recipients_count Liczba adresatów
- * \param recipients Wskaźnik do tablicy z numerami adresatów
- * \param message Treść wiadomości
- * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu.
-int gg_send_message_confer(struct gg_session *sess, int msgclass,
- int recipients_count, uin_t *recipients, const unsigned char *message)
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message_confer("
- "%p, %d, %d, %p, %p);\n", sess, msgclass, recipients_count,
- return gg_send_message_common(sess, msgclass, recipients_count,
- (const unsigned char*)"\x02\x06\x00\x00\x00\x08\x00\x00\x00",
- * Wysyła wiadomość formatowaną w ramach konferencji.
- * Zwraca losowy numer sekwencyjny, który można zignorować albo wykorzystać
- * \param sess Struktura sesji
- * \param msgclass Klasa wiadomości
- * \param recipients_count Liczba adresatów
- * \param recipients Wskaźnik do tablicy z numerami adresatów
- * \param message Treść wiadomości
- * \param format Informacje o formatowaniu
- * \param formatlen Długość informacji o formatowaniu
- * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu.
-int gg_send_message_confer_richtext(struct gg_session *sess, int msgclass,
- int recipients_count, uin_t *recipients, const unsigned char *message,
- const unsigned char *format, int formatlen)
- gg_debug_session(sess, GG_DEBUG_FUNCTION,
- "** gg_send_message_confer_richtext(%p, %d, %d, %p, %p, %p, "
- "%d);\n", sess, msgclass, recipients_count, recipients, message,
- return gg_send_message_common(sess, msgclass, recipients_count, recipients, message, format, formatlen, NULL);
- * Wysyła formatowaną wiadomość HTML w ramach konferencji.
- * Zwraca losowy numer sekwencyjny, który można zignorować albo wykorzystać
- * \param sess Struktura sesji
- * \param msgclass Klasa wiadomości
- * \param recipients_count Liczba adresatów
- * \param recipients Wskaźnik do tablicy z numerami adresatów
- * \param html_message Treść wiadomości HTML
- * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu.
-int gg_send_message_confer_html(struct gg_session *sess, int msgclass,
- int recipients_count, uin_t *recipients,
- const unsigned char *html_message)
- gg_debug_session(sess, GG_DEBUG_FUNCTION,
- "** gg_send_message_confer_html(%p, %d, %d, %p, %p);\n", sess,
- msgclass, recipients_count, recipients, html_message);
- return gg_send_message_common(sess, msgclass, recipients_count, recipients, NULL, NULL, 0, html_message);
- * Wysyła wiadomość binarną przeznaczoną dla klienta.
- * Wiadomości między klientami przesyła się np. w celu wywołania zwrotnego
- * połączenia bezpośredniego. Funkcja zwraca losowy numer sekwencyjny,
- * który można zignorować albo wykorzystać do potwierdzenia.
- * \param sess Struktura sesji
- * \param msgclass Klasa wiadomości
- * \param recipient Numer adresata
- * \param message Treść wiadomości
- * \param message_len Długość wiadomości
- * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu.
-int gg_send_message_ctcp(struct gg_session *sess, int msgclass, uin_t recipient,
- const unsigned char *message, int message_len)
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message_ctcp(%p, "
- "%d, %u, ...);\n", sess, msgclass, recipient);
- if (sess->state != GG_STATE_CONNECTED) {
- s.recipient = gg_fix32(recipient);
- s.msgclass = gg_fix32(msgclass);
- return gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), message, message_len, NULL);
- * Wysyła żądanie obrazka o podanych parametrach.
- * Wiadomości obrazkowe nie zawierają samych obrazków, a tylko ich rozmiary
- * i sumy kontrolne. Odbiorca najpierw szuka obrazków w swojej pamięci
- * podręcznej i dopiero gdy ich nie znajdzie, wysyła żądanie do nadawcy.
- * Wynik zostanie przekazany zdarzeniem \c GG_EVENT_IMAGE_REPLY.
- * \param sess Struktura sesji
- * \param recipient Numer adresata
- * \param size Rozmiar obrazka w bajtach
- * \param crc32 Suma kontrola obrazka
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_image_request(struct gg_session *sess, uin_t recipient, int size, uint32_t crc32)
- struct gg_msg_image_request r;
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_image_request(%p, %d, "
- "%u, 0x%.4x);\n", sess, recipient, size, crc32);
- if (sess->state != GG_STATE_CONNECTED) {
- s.recipient = gg_fix32(recipient);
- s.msgclass = gg_fix32(GG_CLASS_MSG);
- r.flag = GG_MSG_OPTION_IMAGE_REQUEST;
- r.size = gg_fix32(size);
- r.crc32 = gg_fix32(crc32);
- res = gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), &dummy, 1, &r, sizeof(r), NULL);
- struct gg_image_queue *q = malloc(sizeof(*q));
- gg_debug_session(sess, GG_DEBUG_MISC,
- "// gg_image_request() not enough memory for "
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_image_request() not enough memory for image\n");
- memset(q, 0, sizeof(*q));
- struct gg_image_queue *qq;
- for (qq = sess->images; qq->next; qq = qq->next);
- * Wysyła żądany obrazek.
- * \param sess Struktura sesji
- * \param recipient Numer adresata
- * \param filename Nazwa pliku
- * \param image Bufor z obrazkiem
- * \param size Rozmiar obrazka
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_image_reply(struct gg_session *sess, uin_t recipient, const char *filename, const char *image, int size)
- struct gg_session_private *p;
- struct gg_msg_image_reply *r;
- gg_imgout_queue_t *queue = NULL, *queue_end = NULL;
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_image_reply(%p, %d, "
- "\"%s\", %p, %d);\n", sess, recipient, filename, image, size);
- if (!sess || !filename || !image) {
- p = sess->private_data;
- if (sess->state != GG_STATE_CONNECTED) {
- /* wytnij ścieżki, zostaw tylko nazwę pliku */
- while ((tmp = strrchr(filename, '/')) || (tmp = strrchr(filename, '\\')))
- if (strlen(filename) < 1 || strlen(filename) > 1024) {
- s.recipient = gg_fix32(recipient);
- s.msgclass = gg_fix32(GG_CLASS_MSG);
- r->flag = GG_MSG_OPTION_IMAGE_REPLY;
- r->size = gg_fix32(size);
- r->crc32 = gg_fix32(gg_crc32(0, (const unsigned char*) image, size));
- size_t buflen, chunklen;
- /* \0 + struct gg_msg_image_reply */
- buflen = sizeof(struct gg_msg_image_reply) + 1;
- /* w pierwszym kawałku jest nazwa pliku */
- if (r->flag == GG_MSG_OPTION_IMAGE_REPLY) {
- strcpy(buf + buflen, filename);
- buflen += strlen(filename) + 1;
- chunklen = ((size_t) size >= sizeof(buf) - buflen) ? (sizeof(buf) - buflen) : (size_t) size;
- memcpy(buf + buflen, image, chunklen);
- it = gg_new0(sizeof(gg_imgout_queue_t));
- queue = queue_end = it;
- memcpy(&it->msg_hdr, &s, sizeof(s));
- memcpy(it->buf, buf, buflen + chunklen);
- it->buf_len = buflen + chunklen;
- r->flag = GG_MSG_OPTION_IMAGE_REPLY_MORE;
- queue_end = p->imgout_queue;
- while (queue_end->next)
- queue_end = queue_end->next;
- queue_end->next = queue;
- p->imgout_queue = queue;
- gg_image_sendout(sess);
-void gg_image_sendout(struct gg_session *sess)
- struct gg_session_private *p = sess->private_data;
- while (p->imgout_waiting_ack < GG_IMGOUT_WAITING_MAX && p->imgout_queue) {
- gg_imgout_queue_t *it = p->imgout_queue;
- p->imgout_queue = p->imgout_queue->next;
- p->imgout_waiting_ack++;
- res = gg_send_packet(sess, GG_SEND_MSG,
- &it->msg_hdr, sizeof(it->msg_hdr),
-static int gg_notify105_ex(struct gg_session *sess, uin_t *userlist, char *types, int count)
- if (!userlist || !count)
- return gg_send_packet(sess, GG_NOTIFY105_LIST_EMPTY, NULL);
- gg_tvbuilder_t *tvb = gg_tvbuilder_new(sess, NULL);
- gg_tvbuilder_expected_size(tvb, 2100);
- size_t prev_size = gg_tvbuilder_get_size(tvb);
- gg_tvbuilder_write_uin(tvb, userlist[i]);
- gg_tvbuilder_write_uint8(tvb,
- (types == NULL) ? GG_USER_NORMAL : types[i]);
- /* Oryginalny klient wysyła maksymalnie 2048 bajtów
- * danych w każdym pakiecie tego typu.
- if (gg_tvbuilder_get_size(tvb) > 2048) {
- gg_tvbuilder_strip(tvb, prev_size);
- if (!gg_tvbuilder_send(tvb, (i < count) ?
- GG_NOTIFY105_FIRST : GG_NOTIFY105_LAST))
- * Wysyła do serwera listę kontaktów.
- * Funkcja informuje serwer o liście kontaktów, których statusy będą
- * obserwowane lub kontaktów, które bedą blokowane. Dla każdego z \c count
- * kontaktów tablica \c userlist zawiera numer, a tablica \c types rodzaj
- * kontaktu (\c GG_USER_NORMAL, \c GG_USER_OFFLINE, \c GG_USER_BLOCKED).
- * Listę kontaktów należy \b zawsze wysyłać po połączeniu, nawet jeśli
- * \param sess Struktura sesji
- * \param userlist Wskaźnik do tablicy numerów kontaktów
- * \param types Wskaźnik do tablicy rodzajów kontaktów. Jeżeli NULL, wszystkie kontakty są typu GG_USER_NORMAL.
- * \param count Liczba kontaktów
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_notify_ex(struct gg_session *sess, uin_t *userlist, char *types, int count)
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_notify_ex(%p, %p, %p, %d);\n", sess, userlist, types, count);
- if (sess->state != GG_STATE_CONNECTED) {
- if (sess->protocol_version >= GG_PROTOCOL_VERSION_110)
- return gg_notify105_ex(sess, userlist, types, count);
- if (!userlist || !count)
- return gg_send_packet(sess, GG_LIST_EMPTY, NULL);
- int part_count, packet_type;
- packet_type = GG_NOTIFY_FIRST;
- packet_type = GG_NOTIFY_LAST;
- if (!(n = (struct gg_notify*) malloc(sizeof(*n) * part_count)))
- for (i = 0; i < part_count; i++) {
- n[i].uin = gg_fix32(userlist[i]);
- n[i].dunno1 = GG_USER_NORMAL;
- n[i].dunno1 = types[i];
- if (gg_send_packet(sess, packet_type, n, sizeof(*n) * part_count, NULL) == -1) {
- userlist += part_count;
- * Wysyła do serwera listę kontaktów.
- * Funkcja jest odpowiednikiem \c gg_notify_ex(), gdzie wszystkie kontakty
- * są rodzaju \c GG_USER_NORMAL.
- * \param sess Struktura sesji
- * \param userlist Wskaźnik do tablicy numerów kontaktów
- * \param count Liczba kontaktów
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_notify(struct gg_session *sess, uin_t *userlist, int count)
- return gg_notify_ex(sess, userlist, NULL, count);
- * Dodaje do listy kontaktów dany numer w trakcie połączenia. Aby zmienić
- * rodzaj kontaktu (np. z normalnego na zablokowany), należy najpierw usunąć
- * poprzedni rodzaj, ponieważ serwer operuje na maskach bitowych.
- * \param sess Struktura sesji
- * \param uin Numer kontaktu
- * \param type Rodzaj kontaktu
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_add_notify_ex(struct gg_session *sess, uin_t uin, char type)
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_add_notify_ex(%p, %u, %d);\n", sess, uin, type);
- if (sess->state != GG_STATE_CONNECTED) {
- if (sess->protocol_version >= GG_PROTOCOL_VERSION_110) {
- gg_tvbuilder_t *tvb = gg_tvbuilder_new(sess, NULL);
- gg_tvbuilder_expected_size(tvb, 16);
- gg_tvbuilder_write_uin(tvb, uin);
- gg_tvbuilder_write_uint8(tvb, type);
- if (!gg_tvbuilder_send(tvb, GG_ADD_NOTIFY105))
- struct gg_add_remove a;
- return gg_send_packet(sess, GG_ADD_NOTIFY, &a, sizeof(a), NULL);
- * Funkcja jest odpowiednikiem \c gg_add_notify_ex(), gdzie rodzaj wszystkich
- * kontaktów to \c GG_USER_NORMAL.
- * \param sess Struktura sesji
- * \param uin Numer kontaktu
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_add_notify(struct gg_session *sess, uin_t uin)
- return gg_add_notify_ex(sess, uin, GG_USER_NORMAL);
- * Usuwa z listy kontaktów dany numer w trakcie połączenia.
- * \param sess Struktura sesji
- * \param uin Numer kontaktu
- * \param type Rodzaj kontaktu
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_remove_notify_ex(struct gg_session *sess, uin_t uin, char type)
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_remove_notify_ex(%p, %u, %d);\n", sess, uin, type);
- if (sess->state != GG_STATE_CONNECTED) {
- if (sess->protocol_version >= GG_PROTOCOL_VERSION_110) {
- gg_tvbuilder_t *tvb = gg_tvbuilder_new(sess, NULL);
- gg_tvbuilder_expected_size(tvb, 16);
- gg_tvbuilder_write_uin(tvb, uin);
- gg_tvbuilder_write_uint8(tvb, type);
- if (!gg_tvbuilder_send(tvb, GG_REMOVE_NOTIFY105))
- struct gg_add_remove a;
- return gg_send_packet(sess, GG_REMOVE_NOTIFY, &a, sizeof(a), NULL);
- * Funkcja jest odpowiednikiem \c gg_add_notify_ex(), gdzie rodzaj wszystkich
- * kontaktów to \c GG_USER_NORMAL.
- * \param sess Struktura sesji
- * \param uin Numer kontaktu
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_remove_notify(struct gg_session *sess, uin_t uin)
- return gg_remove_notify_ex(sess, uin, GG_USER_NORMAL);
- * Wysyła do serwera zapytanie dotyczące listy kontaktów.
- * Funkcja służy do importu lub eksportu listy kontaktów do serwera.
- * W odróżnieniu od funkcji \c gg_notify(), ta lista kontaktów jest przez
- * serwer jedynie przechowywana i nie ma wpływu na połączenie. Format
- * listy kontaktów jest ignorowany przez serwer, ale ze względu na
- * kompatybilność z innymi klientami, należy przechowywać dane w tym samym
- * formacie co oryginalny klient Gadu-Gadu.
- * Program nie musi się przejmować fragmentacją listy kontaktów wynikającą
- * z protokołu -- wysyła i odbiera kompletną listę.
- * \param sess Struktura sesji
- * \param type Rodzaj zapytania
- * \param request Treść zapytania (może być równe NULL)
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
- * \ingroup importexport
-int gg_userlist_request(struct gg_session *sess, char type, const char *request)
- if (sess->state != GG_STATE_CONNECTED) {
- sess->userlist_blocks = 1;
- return gg_send_packet(sess, GG_USERLIST_REQUEST, &type, sizeof(type), NULL);
- sess->userlist_blocks = 0;
- sess->userlist_blocks++;
- if (gg_send_packet(sess, GG_USERLIST_REQUEST, &type, sizeof(type), request, 2047, NULL) == -1)
- if (type == GG_USERLIST_PUT)
- type = GG_USERLIST_PUT_MORE;
- sess->userlist_blocks++;
- return gg_send_packet(sess, GG_USERLIST_REQUEST, &type, sizeof(type), request, len, NULL);
- * Wysyła do serwera zapytanie dotyczące listy kontaktów (10.0).
- * Funkcja służy do importu lub eksportu listy kontaktów do serwera.
- * W odróżnieniu od funkcji \c gg_notify(), ta lista kontaktów jest przez
- * serwer jedynie przechowywana i nie ma wpływu na połączenie. Format
- * listy kontaktów jest jednak weryfikowany przez serwer, który stara się
- * synchronizować listę kontaktów zapisaną w formatach GG 7.0 oraz GG 10.0.
- * Serwer przyjmuje listy kontaktów przysłane w formacie niezgodnym z podanym
- * jako \c format_type, ale nie zachowuje ich, a przesłanie takiej listy jest
- * równoznaczne z usunięciem listy kontaktów.
- * Program nie musi się przejmować kompresją listy kontaktów zgodną
- * z protokołem -- wysyła i odbiera kompletną listę zapisaną czystym tekstem.
- * \param sess Struktura sesji
- * \param type Rodzaj zapytania
- * \param version Numer ostatniej znanej programowi wersji listy kontaktów lub 0
- * \param format_type Typ formatu listy kontaktów
- * \param request Treść zapytania (może być równe NULL)
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
- * \ingroup importexport
-int gg_userlist100_request(struct gg_session *sess, char type,
- unsigned int version, char format_type, const char *request)
- struct gg_userlist100_request pkt;
- unsigned char *zrequest;
- if (sess->state != GG_STATE_CONNECTED) {
- pkt.version = gg_fix32(version);
- pkt.format_type = format_type;
- return gg_send_packet(sess, GG_USERLIST100_REQUEST, &pkt, sizeof(pkt), NULL);
- zrequest = gg_deflate(request, &zrequest_len);
- if (zrequest == NULL) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_userlist100_request() gg_deflate() failed\n");
- ret = gg_send_packet(sess, GG_USERLIST100_REQUEST, &pkt, sizeof(pkt), zrequest, zrequest_len, NULL);
- * Informuje rozmówcę o pisaniu wiadomości.
- * \param sess Struktura sesji
- * \param recipient Numer adresata
- * \param length Długość wiadomości lub 0 jeśli jest pusta
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_typing_notification(struct gg_session *sess, uin_t recipient, int length){
- struct gg_typing_notification pkt;
- pkt.length = gg_fix16(length);
- uin = gg_fix32(recipient);
- memcpy(&pkt.uin, &uin, sizeof(uin_t));
- return gg_send_packet(sess, GG_TYPING_NOTIFICATION, &pkt, sizeof(pkt), NULL);
- * Rozłącza inną sesję multilogowania.
- * \param gs Struktura sesji
- * \param conn_id Sesja do rozłączenia
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_multilogon_disconnect(struct gg_session *gs, gg_multilogon_id_t conn_id)
- struct gg_multilogon_disconnect pkt;
- return gg_send_packet(gs, GG_MULTILOGON_DISCONNECT, &pkt, sizeof(pkt), NULL);
- * Tworzy nową konferencję (11.0).
- * \param gs Struktura sesji
- * \return Numer sekwencyjny (ten sam, co w \c gg_event_chat_created), lub -1
-int gg_chat_create(struct gg_session *gs)
- struct gg_chat_create pkt;
- if (!gg_required_proto(gs, GG_PROTOCOL_VERSION_110))
- pkt.seq = gg_fix32(seq);
- if (gg_send_packet(gs, GG_CHAT_CREATE, &pkt, sizeof(pkt), NULL) == -1)
- * Zaprasza nowych użytkowników do konferencji (11.0).
- * \param gs Struktura sesji
- * \param id Identyfikator konferencji
- * \param participants Lista użytkowników do zaproszenia
- * \param participants_count Liczba użytkowników
- * \return Numer sekwencyjny w przypadku powodzenia (ten sam, co w
- * \c gg_event_chat_invite_ack), lub -1 w przypadku błędu
-int gg_chat_invite(struct gg_session *gs, uint64_t id, uin_t *participants,
- unsigned int participants_count)
- struct gg_chat_invite pkt;
- struct gg_chat_participant
- struct gg_chat_participant *participants_list;
- size_t participants_list_size;
- if (!gg_required_proto(gs, GG_PROTOCOL_VERSION_110))
- if (participants_count == 0 || participants_count >=
- ~(unsigned int)0 / sizeof(struct gg_chat_participant))
- participants_list_size = sizeof(struct gg_chat_participant) *
- participants_list = malloc(participants_list_size);
- if (participants_list == NULL)
- pkt.seq = gg_fix32(seq);
- pkt.participants_count = gg_fix32(participants_count);
- for (i = 0; i < participants_count; i++) {
- participants_list[i].uin = gg_fix32(participants[i]);
- participants_list[i].dummy = gg_fix32(0x1e);
- ret = gg_send_packet(gs, GG_CHAT_INVITE,
- participants_list, participants_list_size,
- free(participants_list);
- * Opuszcza konferencję (11.0).
- * \param gs Struktura sesji
- * \param id Identyfikator konferencji
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_chat_leave(struct gg_session *gs, uint64_t id)
- struct gg_chat_leave pkt;
- if (!gg_required_proto(gs, GG_PROTOCOL_VERSION_110))
- pkt.seq = gg_fix32(seq);
- if (gg_send_packet(gs, GG_CHAT_LEAVE, &pkt, sizeof(pkt), NULL) == -1)
- * Wysyła wiadomość w ramach konferencji (11.0).
- * \param gs Struktura sesji
- * \param id Identyfikator konferencji
- * \param message Wiadomość
- * \param is_html 1, jeżeli wiadomość jest zapisana jako HTML, 0 w p.p.
- * \return Numer sekwencyjny (taki sam, jak w \c gg_event_chat_send_msg_ack)
- * jeśli się powiodło, -1 w przypadku błędu
-int gg_chat_send_message(struct gg_session *gs, uint64_t id, const char *message, int is_html)
- if (!gg_required_proto(gs, GG_PROTOCOL_VERSION_110))
- return gg_send_message_110(gs, 0, id, message, is_html);
- * Sprawdza czy biblioteka obsługuje daną funkcję.
- * \param feature Identyfikator funkcji.
- * \return Wartość niezerowa jeśli funkcja jest obsłgiwana.
-int gg_libgadu_check_feature(gg_libgadu_feature_t feature)
- case GG_LIBGADU_FEATURE_SSL:
-#if defined(GG_CONFIG_HAVE_OPENSSL) || defined(GG_CONFIG_HAVE_GNUTLS)
- case GG_LIBGADU_FEATURE_PTHREAD:
-#ifdef GG_CONFIG_HAVE_PTHREAD
- case GG_LIBGADU_FEATURE_USERLIST100:
-#ifdef GG_CONFIG_HAVE_ZLIB
- /* Celowo nie ma default, żeby kompilator wyłapał brakujące funkcje */
-static void gg_socket_manager_error(struct gg_session *sess, enum gg_failure_t failure)
- struct gg_session_private *p = sess->private_data;
- p->socket_failure = failure;
- if (socketpair(AF_LOCAL, SOCK_STREAM, 0, pipes) == -1) {
- gg_debug(GG_DEBUG_MISC, "// gg_socket_manager_error() unable to"
- " create pipes (errno=%d, %s)\n", errno,
- p->socket_is_external = 0;
- sess->check = GG_CHECK_READ;
- sess->state = GG_STATE_ERROR;
- if (send(pipes[0], &dummy, sizeof(dummy), 0) != sizeof(dummy)) {
- gg_debug(GG_DEBUG_MISC, "// gg_socket_manager_error() unable to"
- " send via pipe (errno=%d, %s)\n", errno,
-int gg_compat_feature_is_enabled(struct gg_session *sess, gg_compat_feature_t feature)
- level = sess->private_data->compatibility;
- case GG_COMPAT_FEATURE_ACK_EVENT:
- case GG_COMPAT_FEATURE_LEGACY_CONFER:
- return (level < GG_COMPAT_1_12_0);
-static gg_msg_list_t * gg_compat_find_sent_message(struct gg_session *sess, int seq, int remove)
- struct gg_session_private *p = sess->private_data;
- gg_msg_list_t *it, *previous = NULL;
- for (it = p->sent_messages; it; it = it->next) {
- p->sent_messages = it->next;
- previous->next = it->next;
-static void gg_compat_message_cleanup(struct gg_session *sess)
- struct gg_session_private *p = sess->private_data;
- while (p->sent_messages) {
- gg_msg_list_t *next = p->sent_messages->next;
- free(p->sent_messages->recipients);
- free(p->sent_messages);
- p->sent_messages = next;
-static void gg_compat_message_sent(struct gg_session *sess, int seq, size_t recipients_count, uin_t *recipients)
- struct gg_session_private *p = sess->private_data;
- if (sess->protocol_version < GG_PROTOCOL_VERSION_110)
- if (!gg_compat_feature_is_enabled(sess, GG_COMPAT_FEATURE_ACK_EVENT))
- sm = gg_compat_find_sent_message(sess, seq, 0);
- sm = gg_new0(sizeof(gg_msg_list_t));
- sm->next = p->sent_messages;
- old_count = sm->recipients_count;
- sm->recipients_count += recipients_count;
- new_recipients = realloc(sm->recipients, sizeof(uin_t) * sm->recipients_count);
- if (new_recipients == NULL) {
- gg_debug_session(sess, GG_DEBUG_MISC | GG_DEBUG_ERROR,
- "// gg_compat_message_sent() not enough memory\n");
- sm->recipients = new_recipients;
- for (i = 0; i < recipients_count; i++)
- sm->recipients[old_count + i] = recipients[i];
-void gg_compat_message_ack(struct gg_session *sess, int seq)
- if (sess->protocol_version < GG_PROTOCOL_VERSION_110)
- if (!gg_compat_feature_is_enabled(sess, GG_COMPAT_FEATURE_ACK_EVENT))
- sm = gg_compat_find_sent_message(sess, seq, 1);
- for (i = 0; i < sm->recipients_count; i++) {
- qev = gg_eventqueue_add(sess);
- qev->type = GG_EVENT_ACK;
- qev->event.ack.status = GG_ACK_DELIVERED;
- qev->event.ack.recipient = sm->recipients[i];
- qev->event.ack.seq = seq;
- * Odbiera nowo utworzone gniazdo TCP/TLS.
- * Po wywołaniu tej funkcji należy zacząć obserwować deskryptor sesji (nawet
- * w przypadku niepowodzenia).
- * Jeżeli gniazdo nie zostanie obsłużone, należy je zniszczyć.
- * \param handle Uchwyt gniazda
- * \param priv Dane prywatne biblioteki libgadu
- * \param fd Deskryptor nowo utworzonego gniazda, lub -1 w przypadku błędu
- * \return Wartość różna od zera, jeżeli gniazdo zostało obsłużone, 0 w przeciwnym przypadku
- * \ingroup socketmanager
-int gg_socket_manager_connected(void *handle, void *priv, int fd)
- struct gg_session *sess = priv;
- struct gg_session_private *p = sess->private_data;
- if (p->socket_handle != handle) {
- gg_debug_session(sess, GG_DEBUG_MISC | GG_DEBUG_ERROR,
- "// gg_socket_manager_connected() invalid handle\n");
- gg_debug_session(sess, GG_DEBUG_MISC | GG_DEBUG_ERROR,
- "// gg_socket_manager_connected() connection error\n");
- p->socket_handle = NULL;
- gg_socket_manager_error(sess, GG_FAILURE_CONNECTING);
- if (p->socket_next_state == GG_STATE_TLS_NEGOTIATION) {
- if (gg_session_init_ssl(sess) == -1) {
- gg_debug_session(sess, GG_DEBUG_MISC | GG_DEBUG_ERROR,
- "// gg_socket_manager_connected() couldn't "
- p->socket_handle = NULL;
- gg_socket_manager_error(sess, GG_FAILURE_TLS);
- p->socket_is_external = 1;
- sess->timeout = GG_DEFAULT_TIMEOUT;
- sess->state = p->socket_next_state;
- gg_debug_session(sess, GG_DEBUG_MISC, "// next state=%s\n",
- gg_debug_state(p->socket_next_state));
- if (p->socket_next_state == GG_STATE_READING_KEY)
- sess->check = GG_CHECK_READ;
- sess->check = GG_CHECK_WRITE;
- * c-indentation-style: k&r
- * indent-tabs-mode: notnil
--- a/libpurple/protocols/gg/lib/libgadu.h Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2639 +0,0 @@
- * (C) Copyright 2001-2009 Wojtek Kaniewski <wojtekka@irc.pl>
- * Robert J. Woźny <speedy@ziew.org>
- * Arkadiusz Miśkiewicz <arekm@pld-linux.org>
- * Tomasz Chiliński <chilek@chilan.com>
- * Piotr Wysocki <wysek@linux.bydg.org>
- * Dawid Jarosz <dawjar@poczta.onet.pl>
- * Jakub Zawadzki <darkjames@darkjames.ath.cx>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
- * \brief Główny plik nagłówkowy biblioteki
-#ifndef LIBGADU_LIBGADU_H
-#define LIBGADU_LIBGADU_H
-/* Defined if libgadu was compiled for bigendian machine. */
-#undef GG_CONFIG_BIGENDIAN
-/* Defined if this machine has gethostbyname_r(). */
-#undef GG_CONFIG_HAVE_GETHOSTBYNAME_R
-/* Defined if libgadu was compiled and linked with fork support. */
-#undef GG_CONFIG_HAVE_FORK
-/* Defined if libgadu was compiled and linked with pthread support. */
-#undef GG_CONFIG_HAVE_PTHREAD
-/* Defined if pthread resolver is the default one. */
-#undef GG_CONFIG_PTHREAD_DEFAULT
-/* Defined if this machine has C99-compiliant vsnprintf(). */
-#undef GG_CONFIG_HAVE_C99_VSNPRINTF
-/* Defined if this machine has va_copy(). */
-#undef GG_CONFIG_HAVE_VA_COPY
-/* Defined if this machine has __va_copy(). */
-#undef GG_CONFIG_HAVE___VA_COPY
-/* Defined if this machine supports long long. */
-#undef GG_CONFIG_HAVE_LONG_LONG
-/* Defined if libgadu was compiled and linked with GnuTLS support. */
-#undef GG_CONFIG_HAVE_GNUTLS
-/* Defined if libgadu was compiled and linked with OpenSSL support. */
-#undef GG_CONFIG_HAVE_OPENSSL
-/* Defined if libgadu was compiled and linked with zlib support. */
-#undef GG_CONFIG_HAVE_ZLIB
-/* Defined if uintX_t types are defined in <stdint.h>. */
-#undef GG_CONFIG_HAVE_STDINT_H
-/* Defined if uintX_t types are defined in <inttypes.h>. */
-#undef GG_CONFIG_HAVE_INTTYPES_H
-/* Defined if uintX_t types are defined in <sys/inttypes.h>. */
-#undef GG_CONFIG_HAVE_SYS_INTTYPES_H
-/* Defined if uintX_t types are defined in <sys/int_types.h>. */
-#undef GG_CONFIG_HAVE_SYS_INT_TYPES_H
-/* Defined if uintX_t types are defined in <sys/types.h>. */
-#undef GG_CONFIG_HAVE_SYS_TYPES_H
-/* Defined if this machine has uint64_t. */
-#undef GG_CONFIG_HAVE_UINT64_T
-/* Defined if libgadu is GPL compliant (was not linked with OpenSSL or any
- other non-GPL compliant library support). */
-#undef GG_CONFIG_IS_GPL_COMPLIANT
-#ifdef GG_CONFIG_HAVE_OPENSSL
-#include <openssl/ssl.h>
-#ifdef GG_CONFIG_HAVE_STDINT_H
-# ifdef GG_CONFIG_HAVE_INTTYPES_H
-# ifdef GG_CONFIG_HAVE_SYS_INTTYPES_H
-# include <sys/inttypes.h>
-# ifdef GG_CONFIG_HAVE_SYS_INT_TYPES_H
-# include <sys/int_types.h>
-# ifdef GG_CONFIG_HAVE_SYS_TYPES_H
-/* ISO C 9X: 7.18 Integer types <stdint.h> */
-typedef unsigned char uint8_t;
-typedef unsigned short uint16_t;
-typedef unsigned int uint32_t;
-#ifndef GG_CONFIG_HAVE_UINT64_T
-typedef unsigned long long uint64_t;
-typedef SSIZE_T ssize_t;
-#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4))
-# define GG_GNUC_PRINTF(format_idx, arg_idx) \
- __attribute__((format (printf, (format_idx), (arg_idx))))
-# define GG_GNUC_PRINTF(format_idx, arg_idx)
- * Identyfikator połączenia bezpośredniego Gadu-Gadu 7.x.
- * Identyfikator sesji multilogowania.
- * Makro deklarujące pola wspólne dla struktur sesji.
-#define gg_common_head(x) \
- int fd; /**< Obserwowany deskryptor */ \
- int check; /**< Informacja o żądaniu odczytu/zapisu (patrz \ref gg_check_t) */ \
- int state; /**< Aktualny stan połączenia (patrz \ref gg_state_t) */ \
- int error; /**< Kod błędu dla \c GG_STATE_ERROR (patrz \ref gg_error_t) */ \
- int type; /**< Rodzaj sesji (patrz \ref gg_session_t) */ \
- int id; /**< Identyfikator sesji */ \
- int timeout; /**< Czas pozostały do zakończenia stanu */ \
- int (*callback)(x*); /**< Funkcja zwrotna */ \
- void (*destroy)(x*); /**< Funkcja zwalniania zasobów */
- * Struktura wspólna dla wszystkich sesji i połączeń. Pozwala na proste
- * rzutowanie niezależne od rodzaju połączenia.
- gg_common_head(struct gg_common)
-struct gg_session_private;
- * Sposób rozwiązywania nazw serwerów.
- GG_RESOLVER_DEFAULT = 0, /**< Domyślny sposób rozwiązywania nazw (jeden z poniższych) */
- GG_RESOLVER_FORK, /**< Rozwiązywanie nazw bazujące na procesach */
- GG_RESOLVER_PTHREAD, /**< Rozwiązywanie nazw bazujące na wątkach */
- GG_RESOLVER_CUSTOM, /**< Funkcje rozwiązywania nazw dostarczone przed aplikację */
- GG_RESOLVER_WIN32, /**< Rozwiązywanie nazw bazujące na wątkach Win32 */
- GG_RESOLVER_INVALID = -1 /**< Nieprawidłowy sposób rozwiązywania nazw (wynik \c gg_session_get_resolver) */
- * Rodzaj kodowania znaków.
- GG_ENCODING_CP1250 = 0, /**< Kodowanie CP1250 */
- GG_ENCODING_UTF8, /**< Kodowanie UTF-8 */
- GG_ENCODING_INVALID = -1 /**< Nieprawidłowe kodowanie */
- * Stopień kompatybilności ze starymi wersjami API.
- GG_COMPAT_LEGACY = 0, /**< Całkowita kompatybilność (nie wyłącza żadnych funkcji) */
- GG_COMPAT_1_12_0 = 1 /**< Wyłącza: dostarczanie eventów GG_EVENT_ACK, stary format konferencji */
- * Flaga połączenia szyfrowanego.
- GG_SSL_DISABLED = 0, /**< Połączenie SSL wyłączone */
- GG_SSL_ENABLED, /**< Połączenie SSL włączone gdy dostępne. Błędny certyfikat serwera nie powoduje odrzucenia połączenia. */
- GG_SSL_REQUIRED /**< Połączenie SSL wymagane. Błędny certyfikat serwera powoduje odrzucenie połączenia. */
- * Tworzona przez funkcję \c gg_login(), zwalniana przez \c gg_free_session().
- gg_common_head(struct gg_session)
- int async; /**< Flaga połączenia asynchronicznego */
- int pid; /**< Numer procesu rozwiązującego nazwę serwera */
- int port; /**< Port serwera */
- int seq; /**< Numer sekwencyjny ostatniej wiadomości */
- int last_pong; /**< Czas otrzymania ostatniej ramki utrzymaniowej */
- int last_event; /**< Czas otrzymania ostatniego pakietu */
- struct gg_event *event; /**< Zdarzenie po wywołaniu \c callback */
- uint32_t proxy_addr; /**< Adres serwera pośredniczącego */
- uint16_t proxy_port; /**< Port serwera pośredniczącego */
- uint32_t hub_addr; /**< Adres huba po rozwiązaniu nazwy */
- uint32_t server_addr; /**< Adres serwera otrzymany od huba */
- uint32_t client_addr; /**< Adres gniazda dla połączeń bezpośrednich */
- uint16_t client_port; /**< Port gniazda dla połączeń bezpośrednich */
- uint32_t external_addr; /**< Publiczny adres dla połączeń bezpośrednich */
- uint16_t external_port; /**< Publiczny port dla połączeń bezpośrednich */
- uin_t uin; /**< Własny numer Gadu-Gadu */
- char *password; /**< Hasło (zwalniane po użyciu) */
- int initial_status; /**< Początkowy status */
- int status; /**< Aktualny status */
- char *recv_buf; /**< Bufor na odbierane pakiety. Wskaźnik zawsze maksymalnie wyrównany, tak jak w wyniku działania \c malloc(). */
- int recv_done; /**< Liczba wczytanych bajtów pakietu */
- int recv_left; /**< Liczba pozostałych do wczytania bajtów pakietu */
- int protocol_version; /**< Wersja protokołu (bez flag) */
- char *client_version; /**< Wersja klienta */
- int last_sysmsg; /**< Numer ostatniej wiadomości systemowej */
- char *initial_descr; /**< Początkowy opis statusu */
- void *resolver; /**< Dane prywatne procesu lub wątku rozwiązującego nazwę serwera */
- char *header_buf; /**< Bufor na początek nagłówka pakietu (nieaktualne) */
- unsigned int header_done; /**< Liczba wczytanych bajtów nagłówka pakietu (nieaktualne) */
-#ifdef GG_CONFIG_HAVE_OPENSSL
- SSL *ssl; /**< Struktura TLS */
- SSL_CTX *ssl_ctx; /**< Kontekst sesji TLS */
- void *ssl; /**< Struktura TLS */
- void *ssl_ctx; /**< Kontekst sesji TLS */
- int image_size; /**< Maksymalny rozmiar obsługiwanych obrazków w KiB */
- char *userlist_reply; /**< Bufor z odbieraną listą kontaktów */
- int userlist_blocks; /**< Liczba części listy kontaktów */
- struct gg_image_queue *images; /**< Lista wczytywanych obrazków */
- int hash_type; /**< Rodzaj funkcji skrótu hasła (\c GG_LOGIN_HASH_GG32 lub \c GG_LOGIN_HASH_SHA1) */
- char *send_buf; /**< Bufor z danymi do wysłania */
- int send_left; /**< Liczba bajtów do wysłania */
- struct gg_dcc7 *dcc7_list; /**< Lista połączeń bezpośrednich skojarzonych z sesją */
- int soft_timeout; /**< Flaga mówiąca, że po przekroczeniu \c timeout należy wywołać \c gg_watch_fd() */
- int protocol_flags; /**< Flagi protokołu */
- gg_encoding_t encoding; /**< Rodzaj kodowania znaków */
- gg_resolver_t resolver_type; /**< Sposób rozwiązywania nazw serwerów */
- int (*resolver_start)(int *fd, void **private_data, const char *hostname); /**< Funkcja rozpoczynająca rozwiązywanie nazwy */
- void (*resolver_cleanup)(void **private_data, int force); /**< Funkcja zwalniająca zasoby po rozwiązaniu nazwy */
- int protocol_features; /**< Opcje protokołu */
- int status_flags; /**< Flagi statusu */
- int recv_msg_count; /**< Liczba odebranych wiadomości */
- const char *resolver_host; /**< Nazwa do rozwiązania */
- struct in_addr *resolver_result; /**< Wynik rozwiązywania nazwy */
- unsigned int resolver_index; /**< Indeks aktualnie obsługiwanego wyniku rozwiązywania nazwy */
- unsigned int resolver_count; /**< Liczba wyników rozwiązywania nazwy */
- uint16_t connect_port[2]; /**< Lista portów do połączenia */
- unsigned int connect_index; /**< Indeks aktualnie obsługiwanego portu */
- char *connect_host; /**< Adres serwera Gadu-Gadu, z którym się łączymy */
- gg_ssl_t ssl_flag; /**< Flaga połączenia szyfrowanego */
- struct gg_session_private *private_data; /**< Prywatne dane sesji, nie udostępnione w API */
- * Tworzone przez \c gg_http_connect(), zwalniane przez \c gg_http_free().
- gg_common_head(struct gg_http)
- int async; /**< Flaga połączenia asynchronicznego */
- int pid; /**< Identyfikator procesu rozwiązującego nazwę serwera */
- char *query; /**< Zapytanie HTTP */
- char *header; /**< Odebrany nagłówek */
- int header_size; /**< Rozmiar wczytanego nagłówka */
- char *body; /**< Odebrana strona */
- unsigned int body_size; /**< Rozmiar strony */
- void *data; /**< Dane prywatne usługi HTTP */
- char *user_data; /**< Dane prywatne użytkownika (nie są zwalniane) */
- void *resolver; /**< Dane prywatne procesu lub wątku rozwiązującego nazwę */
- unsigned int body_done; /**< Liczba odebranych bajtów strony */
- gg_resolver_t resolver_type; /**< Sposób rozwiązywania nazw serwerów */
- int (*resolver_start)(int *fd, void **private_data, const char *hostname); /**< Funkcja rozpoczynająca rozwiązywanie nazwy */
- void (*resolver_cleanup)(void **private_data, int force); /**< Funkcja zwalniająca zasoby po rozwiązaniu nazwy */
-#define GG_PACKED __attribute__ ((packed))
-#ifndef GG_IGNORE_DEPRECATED
-#define GG_DEPRECATED __attribute__ ((deprecated))
-#define GG_MAX_PATH 276 /**< Maksymalny rozmiar nazwy pliku w strukturze \c gg_file_info */
- * Odpowiednik struktury WIN32_FIND_DATA z API WIN32.
- * Wykorzystywana przy połączeniach bezpośrednich do wersji Gadu-Gadu 6.x.
- uint32_t mode; /**< dwFileAttributes */
- uint32_t ctime[2]; /**< ftCreationTime */
- uint32_t atime[2]; /**< ftLastAccessTime */
- uint32_t mtime[2]; /**< ftLastWriteTime */
- uint32_t size_hi; /**< nFileSizeHigh */
- uint32_t size; /**< nFileSizeLow */
- uint32_t reserved0; /**< dwReserved0 */
- uint32_t reserved1; /**< dwReserved1 */
- unsigned char filename[GG_MAX_PATH - 14]; /**< cFileName */
- unsigned char short_filename[14]; /**< cAlternateFileName */
-} /** \cond ignore */ GG_PACKED /** \endcond */;
- * Połączenie bezpośrednie do wersji Gadu-Gadu 6.x.
- * Tworzone przez \c gg_dcc_socket_create(), \c gg_dcc_get_file(),
- * \c gg_dcc_send_file() lub \c gg_dcc_voice_chat(), zwalniane przez
- gg_common_head(struct gg_dcc)
- struct gg_event *event; /**< Zdarzenie po wywołaniu \c callback */
- int active; /**< Flaga połączenia aktywnego (nieużywana) */
- int port; /**< Port gniazda nasłuchującego */
- uin_t uin; /**< Własny numer Gadu-Gadu */
- uin_t peer_uin; /**< Numer Gadu-Gadu drugiej strony połączenia */
- int file_fd; /**< deskryptor pliku */
- unsigned int offset; /**< Położenie w pliku */
- unsigned int chunk_size;
- /**< Rozmiar kawałka pliku */
- unsigned int chunk_offset;
- /**< Położenie w aktualnym kawałku pliku */
- struct gg_file_info file_info;
- /**< Informacje o pliku */
- int established; /**< Flaga ustanowienia połączenia */
- char *voice_buf; /**< Bufor na pakiet połączenia głosowego */
- int incoming; /**< Flaga połączenia przychodzącego */
- char *chunk_buf; /**< Bufor na fragment danych */
- uint32_t remote_addr; /**< Adres drugiej strony */
- uint16_t remote_port; /**< Port drugiej strony */
-#define GG_DCC7_HASH_LEN 20 /**< Maksymalny rozmiar skrótu pliku w połączeniach bezpośrenich */
-#define GG_DCC7_FILENAME_LEN 255 /**< Maksymalny rozmiar nazwy pliku w połączeniach bezpośrednich */
-#define GG_DCC7_INFO_LEN 32 /**< Maksymalny rozmiar informacji o połączeniach bezpośrednich */
-#define GG_DCC7_INFO_HASH_LEN 32 /**< Maksymalny rozmiar skrótu ip informacji o połączeniach bezpośrednich */
- * Połączenie bezpośrednie od wersji Gadu-Gadu 7.x.
- gg_common_head(struct gg_dcc7)
- gg_dcc7_id_t cid; /**< Identyfikator połączenia */
- struct gg_event *event; /**< Struktura zdarzenia */
- uin_t uin; /**< Własny numer Gadu-Gadu */
- uin_t peer_uin; /**< Numer Gadu-Gadu drugiej strony połączenia */
- int file_fd; /**< Deskryptor przesyłanego pliku */
- unsigned int offset; /**< Aktualne położenie w przesyłanym pliku */
- unsigned int size; /**< Rozmiar przesyłanego pliku */
- unsigned char filename[GG_DCC7_FILENAME_LEN + 1];
- /**< Nazwa przesyłanego pliku */
- unsigned char hash[GG_DCC7_HASH_LEN];
- /**< Skrót SHA1 przesyłanego pliku */
- int dcc_type; /**< Rodzaj połączenia bezpośredniego */
- int established; /**< Flaga ustanowienia połączenia */
- int incoming; /**< Flaga połączenia przychodzącego */
- int reverse; /**< Flaga połączenia zwrotnego */
- uint32_t local_addr; /**< Adres lokalny */
- uint16_t local_port; /**< Port lokalny */
- uint32_t remote_addr; /**< Adres drugiej strony */
- uint16_t remote_port; /**< Port drugiej strony */
- struct gg_session *sess;
- /**< Sesja do której przypisano połączenie */
- struct gg_dcc7 *next; /**< Następne połączenie w liście */
- int soft_timeout; /**< Flaga mówiąca, że po przekroczeniu \c timeout należy wywołać \c gg_dcc7_watch_fd() */
- int seek; /**< Flaga mówiąca, że można zmieniać położenie w wysyłanym pliku */
- void *resolver; /**< Dane prywatne procesu lub wątku rozwiązującego nazwę serwera */
- int relay; /**< Flaga mówiąca, że laczymy sie przez serwer */
- int relay_index; /**< Numer serwera pośredniczącego, do którego się łączymy */
- int relay_count; /**< Rozmiar listy serwerów pośredniczących */
- struct gg_dcc7_relay *relay_list; /**< Lista serwerów pośredniczących */
- GG_SESSION_GG = 1, /**< Połączenie z serwerem Gadu-Gadu */
- GG_SESSION_HTTP, /**< Połączenie HTTP */
- GG_SESSION_SEARCH, /**< Wyszukiwanie w katalogu publicznym (nieaktualne) */
- GG_SESSION_REGISTER, /**< Rejestracja nowego konta */
- GG_SESSION_REMIND, /**< Przypominanie hasła */
- GG_SESSION_PASSWD, /**< Zmiana hasła */
- GG_SESSION_CHANGE, /**< Zmiana informacji w katalogu publicznym (nieaktualne) */
- GG_SESSION_DCC, /**< Połączenie bezpośrednie (do wersji 6.x) */
- GG_SESSION_DCC_SOCKET, /**< Gniazdo nasłuchujące (do wersji 6.x) */
- GG_SESSION_DCC_SEND, /**< Wysyłanie pliku (do wersji 6.x) */
- GG_SESSION_DCC_GET, /**< Odbieranie pliku (do wersji 6.x) */
- GG_SESSION_DCC_VOICE, /**< Rozmowa głosowa (do wersji 6.x) */
- GG_SESSION_USERLIST_GET, /**< Import listy kontaktów z serwera (nieaktualne) */
- GG_SESSION_USERLIST_PUT, /**< Eksport listy kontaktów do serwera (nieaktualne) */
- GG_SESSION_UNREGISTER, /**< Usuwanie konta */
- GG_SESSION_USERLIST_REMOVE, /**< Usuwanie listy kontaktów z serwera (nieaktualne) */
- GG_SESSION_TOKEN, /**< Pobieranie tokenu */
- GG_SESSION_DCC7_SOCKET, /**< Gniazdo nasłuchujące (od wersji 7.x) */
- GG_SESSION_DCC7_SEND, /**< Wysyłanie pliku (od wersji 7.x) */
- GG_SESSION_DCC7_GET, /**< Odbieranie pliku (od wersji 7.x) */
- GG_SESSION_DCC7_VOICE, /**< Rozmowa głosowa (od wersji 7.x) */
- GG_SESSION_USER0 = 256, /**< Rodzaj zadeklarowany dla użytkownika */
- GG_SESSION_USER1, /**< Rodzaj zadeklarowany dla użytkownika */
- GG_SESSION_USER2, /**< Rodzaj zadeklarowany dla użytkownika */
- GG_SESSION_USER3, /**< Rodzaj zadeklarowany dla użytkownika */
- GG_SESSION_USER4, /**< Rodzaj zadeklarowany dla użytkownika */
- GG_SESSION_USER5, /**< Rodzaj zadeklarowany dla użytkownika */
- GG_SESSION_USER6, /**< Rodzaj zadeklarowany dla użytkownika */
- GG_SESSION_USER7 /**< Rodzaj zadeklarowany dla użytkownika */
- GG_STATE_IDLE = 0, /**< Nie dzieje się nic */
- GG_STATE_RESOLVING, /**< Oczekiwanie na rozwiązanie nazwy serwera */
- GG_STATE_CONNECTING, /**< Oczekiwanie na połączenie */
- GG_STATE_READING_DATA, /**< Oczekiwanie na dane */
- GG_STATE_ERROR, /**< Kod błędu w polu \c error */
- GG_STATE_CONNECTING_HUB, /**< Oczekiwanie na połączenie z hubem */
- GG_STATE_CONNECTING_GG, /**< Oczekiwanie na połączenie z serwerem */
- GG_STATE_READING_KEY, /**< Oczekiwanie na klucz */
- GG_STATE_READING_REPLY, /**< Oczekiwanie na odpowiedź serwera */
- GG_STATE_CONNECTED, /**< Połączono z serwerem */
- GG_STATE_SENDING_QUERY, /**< Wysłano zapytanie HTTP */
- GG_STATE_READING_HEADER, /**< Oczekiwanie na nagłówek HTTP */
- GG_STATE_PARSING, /**< Przetwarzanie danych */
- GG_STATE_DONE, /**< Połączenie zakończone */
- GG_STATE_LISTENING, /* czeka na połączenia */
- GG_STATE_READING_UIN_1, /* czeka na uin peera */
- GG_STATE_READING_UIN_2, /* czeka na swój uin */
- GG_STATE_SENDING_ACK, /* wysyła potwierdzenie dcc */
- GG_STATE_READING_ACK, /* czeka na potwierdzenie dcc */
- GG_STATE_READING_REQUEST, /* czeka na komendę */
- GG_STATE_SENDING_REQUEST, /* wysyła komendę */
- GG_STATE_SENDING_FILE_INFO, /* wysyła informacje o pliku */
- GG_STATE_READING_PRE_FILE_INFO, /* czeka na pakiet przed file_info */
- GG_STATE_READING_FILE_INFO, /* czeka na informacje o pliku */
- GG_STATE_SENDING_FILE_ACK, /* wysyła potwierdzenie pliku */
- GG_STATE_READING_FILE_ACK, /* czeka na potwierdzenie pliku */
- GG_STATE_SENDING_FILE_HEADER, /* wysyła nagłówek pliku */
- GG_STATE_READING_FILE_HEADER, /* czeka na nagłówek */
- GG_STATE_GETTING_FILE, /* odbiera plik */
- GG_STATE_SENDING_FILE, /* wysyła plik */
- GG_STATE_READING_VOICE_ACK, /* czeka na potwierdzenie voip */
- GG_STATE_READING_VOICE_HEADER, /* czeka na rodzaj bloku voip */
- GG_STATE_READING_VOICE_SIZE, /* czeka na rozmiar bloku voip */
- GG_STATE_READING_VOICE_DATA, /* czeka na dane voip */
- GG_STATE_SENDING_VOICE_ACK, /* wysyła potwierdzenie voip */
- GG_STATE_SENDING_VOICE_REQUEST, /* wysyła żądanie voip */
- GG_STATE_READING_TYPE, /* czeka na typ połączenia */
- /* nowe. bez sensu jest to API. */
- GG_STATE_TLS_NEGOTIATION, /**< Negocjacja połączenia szyfrowanego */
- GG_STATE_REQUESTING_ID, /**< Oczekiwanie na nadanie identyfikatora połączenia bezpośredniego */
- GG_STATE_WAITING_FOR_ACCEPT, /**< Oczekiwanie na potwierdzenie lub odrzucenie połączenia bezpośredniego */
- GG_STATE_WAITING_FOR_INFO, /**< Oczekiwanie na informacje o połączeniu bezpośrednim */
- GG_STATE_READING_ID, /**< Odebranie identyfikatora połączenia bezpośredniego */
- GG_STATE_SENDING_ID, /**< Wysłano identyfikator połączenia bezpośredniego */
- GG_STATE_RESOLVING_GG, /**< Oczekiwanie na rozwiązanie nazwy serwera Gadu-Gadu */
- GG_STATE_RESOLVING_RELAY, /**< Oczekiwanie na rozwiązanie nazwy serwera pośredniczącego */
- GG_STATE_CONNECTING_RELAY, /**< Oczekiwanie na połączenie z serwerem pośredniczącym */
- GG_STATE_READING_RELAY, /**< Odbieranie danych */
- GG_STATE_DISCONNECTING, /**< Oczekiwanie na potwierdzenie rozłączenia */
- GG_STATE_CONNECT_HUB, /**< Nawiązanie połączenia z hubem */
- GG_STATE_CONNECT_PROXY_HUB,
- GG_STATE_CONNECT_GG, /**< Nawiązanie połączenia z serwerem */
- GG_STATE_CONNECT_PROXY_GG,
- GG_STATE_CONNECTING_PROXY_HUB,
- GG_STATE_CONNECTING_PROXY_GG,
- GG_STATE_RESOLVE_HUB_SYNC,
- GG_STATE_RESOLVE_HUB_ASYNC,
- GG_STATE_RESOLVE_PROXY_HUB_SYNC,
- GG_STATE_RESOLVE_PROXY_HUB_ASYNC,
- GG_STATE_RESOLVE_PROXY_GG_SYNC,
- GG_STATE_RESOLVE_PROXY_GG_ASYNC,
- GG_STATE_RESOLVE_GG_SYNC,
- GG_STATE_RESOLVE_GG_ASYNC,
- GG_STATE_RESOLVING_HUB,
- GG_STATE_RESOLVING_PROXY_HUB,
- GG_STATE_RESOLVING_PROXY_GG,
- GG_STATE_SEND_PROXY_HUB,
- GG_STATE_SEND_PROXY_GG,
- GG_STATE_SENDING_PROXY_HUB,
- GG_STATE_SENDING_PROXY_GG,
- GG_STATE_READING_PROXY_HUB,
- GG_STATE_READING_PROXY_GG,
- * Informacja o tym, czy biblioteka chce zapisywać i/lub czytać
- * z deskryptora. Maska bitowa.
- GG_CHECK_NONE = 0, /**< Nie sprawdzaj niczego */
- GG_CHECK_WRITE = 1, /**< Sprawdź możliwość zapisu */
- GG_CHECK_READ = 2 /**< Sprawdź możliwość odczytu */
- * Metody nawiązywania połączeń TCP/TLS.
- * \ingroup socketmanager
- GG_SOCKET_MANAGER_TYPE_INTERNAL = 0, /**< Wewnętrzna obsługa gniazd (domyślne). */
- GG_SOCKET_MANAGER_TYPE_TCP, /**< Dostarczona przez aplikację - tylko obsługa TCP. */
- GG_SOCKET_MANAGER_TYPE_TLS /**< Dostarczona przez aplikację - obsługa zarówno TCP, jak i TLS. */
-} gg_socket_manager_type_t;
- * Funkcja dostarczona przez aplikację, tworząca nowe gniazdo TCP/TLS.
- * Po nawiązaniu połączenia aplikacja musi wywołać gg_socket_manager_connected.
- * Jeżeli połączenie jest asynchroniczne, wywołanie musi nastąpić po wyjściu z
- * kontekstu tej funkcji. Dla połączeń synchronicznych z kolei, musi nastąpić
- * jeszcze przed wyjściem z kontekstu.
- * \param cb_data Dane prywatne aplikacji
- * \param host Nazwa hosta
- * \param port Numer portu
- * \param is_tls Flaga określająca, czy ma zostać nawiązane połączenie TLS
- * \param is_async Flaga określająca połączenie asynchroniczne (patrz szczegóły powyżej)
- * \param priv Dane prywatne biblioteki libgadu (do przekazania do gg_socket_manager_connected)
- * \return Uchwyt gniazda
- * \ingroup socketmanager
-typedef void* (*gg_socket_manager_connect_cb_t)(void *cb_data, const char *host, int port, int is_tls, int is_async, void *priv);
- * Niszczy gniazdo i zwalnia wszystkie powiązane z nim zasoby.
- * \param cb_data Dane prywatne aplikacji
- * \param handle Uchwyt gniazda
- * \ingroup socketmanager
-typedef void (*gg_socket_manager_close_cb_t)(void *cb_data, void *handle);
- * Odbiera z gniazda dane binarne.
- * Funkcja powinna zajmować się obsługą TLS, jeżeli gniazdo jest w takim trybie.
- * \param cb_data Dane prywatne aplikacji
- * \param handle Uchwyt gniazda
- * \param buffer Bufor do zapisu danych
- * \param bufsize Rozmiar bufora
- * \return Ilość zapisanych danych, lub -1 (oraz ustawiony errno) w przypadku niepowodzenia
- * \ingroup socketmanager
-typedef ssize_t (*gg_socket_manager_read_cb_t)(void *cb_data, void *handle, unsigned char *buffer, size_t bufsize);
- * Wysyła przez gniazdo dane binarne.
- * Funkcja powinna zajmować się obsługą TLS, jeżeli gniazdo jest w takim trybie.
- * \param cb_data Dane prywatne aplikacji
- * \param handle Uchwyt gniazda
- * \param data Dane do wysłania
- * \param length Rozmiar danych
- * \return Ilość wysłanych danych, lub -1 (oraz ustawiony errno) w przypadku niepowodzenia
- * \ingroup socketmanager
-typedef ssize_t (*gg_socket_manager_write_cb_t)(void *cb_data, void *handle, const unsigned char *data, size_t length);
- * Struktura opisująca funkcje zarządzające gniazdami, jeżeli aplikacja sama je
- * \ingroup socketmanager
- void *cb_data; /**< Dane prywatne aplikacji */
- gg_socket_manager_connect_cb_t connect_cb; /**< Funkcja tworząca nowe gniazdo */
- gg_socket_manager_close_cb_t close_cb; /**< Funkcja niszcząca gniazdo */
- gg_socket_manager_read_cb_t read_cb; /**< Funkcja odczytująca dane z gniazda */
- gg_socket_manager_write_cb_t write_cb; /**< Funkcja wysyłająca dane przez gniazdo */
-int gg_socket_manager_connected(void *handle, void *priv, int fd);
- * Parametry połączenia z serwerem Gadu-Gadu. Parametry zostały przeniesione
- * do struktury, by uniknąć zmian API po rozszerzeniu protokołu i dodaniu
- * kolejnych opcji połączenia. Część parametrów, które nie są już aktualne
- * lub nie mają znaczenia, została usunięta z dokumentacji.
-struct gg_login_params {
- uin_t uin; /**< Numer Gadu-Gadu */
- char *password; /**< Hasło */
- int async; /**< Flaga asynchronicznego połączenia (domyślnie nie) */
- int status; /**< Początkowy status użytkownika (domyślnie \c GG_STATUS_AVAIL) */
- char *status_descr; /**< Początkowy opis użytkownika (domyślnie brak) */
- uint32_t server_addr; /**< Adres serwera Gadu-Gadu (domyślnie pobierany automatycznie) */
- uint16_t server_port; /**< Port serwera Gadu-Gadu (domyślnie pobierany automatycznie) */
- uint32_t client_addr; /**< Adres połączeń bezpośrednich (domyślnie dobierany automatycznie) */
- uint16_t client_port; /**< Port połączeń bezpośrednich (domyślnie dobierany automatycznie) */
- int protocol_version; /**< Wersja protokołu wysyłana do serwera (domyślnie najnowsza obsługiwana) */
- char *client_version; /**< Wersja klienta wysyłana do serwera (domyślnie najnowsza znana) */
- int has_audio; /**< Flaga obsługi połączeń głosowych */
- int last_sysmsg; /**< Numer ostatnio odebranej wiadomości systemowej */
- uint32_t external_addr; /**< Adres publiczny dla połączeń bezpośrednich (domyślnie dobierany automatycznie) */
- uint16_t external_port; /**< Port publiczny dla połączeń bezpośrednich (domyślnie dobierany automatycznie) */
- int tls; /**< Flaga połączenia szyfrowanego (patrz \ref gg_ssl_t) */
- int image_size; /**< Maksymalny rozmiar obsługiwanych obrazków w kilobajtach */
- int era_omnix; /**< Flaga udawania klienta Era Omnix (nieaktualna) */
- int hash_type; /**< Rodzaj skrótu hasła (\c GG_LOGIN_HASH_GG32 lub \c GG_LOGIN_HASH_SHA1, domyślnie SHA1) */
- gg_encoding_t encoding; /**< Rodzaj kodowania używanego w sesji (domyślnie CP1250) */
- gg_resolver_t resolver; /**< Sposób rozwiązywania nazw (patrz \ref build-resolver) */
- int protocol_features; /**< Opcje protokołu (flagi GG_FEATURE_*). */
- int status_flags; /**< Flagi statusu (flagi GG_STATUS_FLAG_*, patrz \ref status). */
- unsigned int struct_size; /**< Rozmiar struktury. To pole powinno być inicjowane wartością sizeof(struct gg_login_params) - w przeciwnym przypadku pola za nim nie będą obsługiwane. Pozwala na rozszerzanie struktury bez łamania ABI. */
- gg_compat_t compatibility; /**< Stopień kompatybilności ze starym API. */
- char *connect_host; /**< Nazwa hosta (oraz opcjonalnie port, podany po dwukropku) serwera Gadu-Gadu (domyślnie pobierany automatycznie) (patrz pole struct_size). */
- gg_socket_manager_type_t socket_manager_type; /**< Wybrana metoda nawiązywania połączeń TCP/TLS (domyślnie wewnętrzna) */
- gg_socket_manager_t socket_manager; /**< Jeżeli wybrano metodę zewnętrzną - konfiguracja jej */
- char **host_white_list; /**< Lista zakończona wskaźnikiem NULL, domen akceptowanych w odpowiedziach od huba (domyślnie wszystkie do tej pory znane). Używane tylko przy GG_SSL_REQUIRED. Pusta lista wyłącza sprawdzanie. */
-#ifdef GG_CONFIG_IS_GPL_COMPLIANT
-int gg_is_gpl_compliant(void);
-struct gg_session *gg_login(const struct gg_login_params *p);
-void gg_free_session(struct gg_session *sess);
-void gg_logoff(struct gg_session *sess);
-int gg_change_status(struct gg_session *sess, int status);
-int gg_change_status_descr(struct gg_session *sess, int status, const char *descr);
-int gg_change_status_descr_time(struct gg_session *sess, int status, const char *descr, int time);
-int gg_change_status_flags(struct gg_session *sess, int flags);
-int gg_send_message(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message);
-int gg_send_message_richtext(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, const unsigned char *format, int formatlen);
-int gg_send_message_html(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *html_message);
-int gg_send_message_confer(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message);
-int gg_send_message_confer_richtext(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message, const unsigned char *format, int formatlen);
-int gg_send_message_confer_html(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *html_message);
-int gg_send_message_ctcp(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, int message_len);
-int gg_ping(struct gg_session *sess);
-int gg_userlist_request(struct gg_session *sess, char type, const char *request);
-int gg_userlist100_request(struct gg_session *sess, char type, unsigned int version, char format_type, const char *request);
-int gg_image_request(struct gg_session *sess, uin_t recipient, int size, uint32_t crc32);
-int gg_image_reply(struct gg_session *sess, uin_t recipient, const char *filename, const char *image, int size);
-int gg_typing_notification(struct gg_session *sess, uin_t recipient, int length);
-uint32_t gg_crc32(uint32_t crc, const unsigned char *buf, int len);
-int gg_session_set_resolver(struct gg_session *gs, gg_resolver_t type);
-gg_resolver_t gg_session_get_resolver(struct gg_session *gs);
-int gg_session_set_custom_resolver(struct gg_session *gs, int (*resolver_start)(int*, void**, const char*), void (*resolver_cleanup)(void**, int));
-int gg_http_set_resolver(struct gg_http *gh, gg_resolver_t type);
-gg_resolver_t gg_http_get_resolver(struct gg_http *gh);
-int gg_http_set_custom_resolver(struct gg_http *gh, int (*resolver_start)(int*, void**, const char*), void (*resolver_cleanup)(void**, int));
-int gg_global_set_resolver(gg_resolver_t type);
-gg_resolver_t gg_global_get_resolver(void);
-int gg_global_set_custom_resolver(int (*resolver_start)(int*, void**, const char*), void (*resolver_cleanup)(void**, int));
-int gg_multilogon_disconnect(struct gg_session *gs, gg_multilogon_id_t conn_id);
-int gg_chat_create(struct gg_session *gs);
-int gg_chat_invite(struct gg_session *gs, uint64_t id, uin_t *participants, unsigned int participants_count);
-int gg_chat_leave(struct gg_session *gs, uint64_t id);
-int gg_chat_send_message(struct gg_session *gs, uint64_t id, const char *message, int is_html);
- GG_EVENT_NONE = 0, /**< Nie wydarzyło się nic wartego uwagi */
- GG_EVENT_MSG, /**< \brief Otrzymano wiadomość. Przekazuje również wiadomości systemowe od numeru 0. */
- GG_EVENT_NOTIFY, /**< \brief Informacja o statusach osób z listy kontaktów (przed 6.0). Zdarzenie należy obsługiwać, jeśli planuje się używać protokołu w wersji starszej niż domyślna. Ostatni element tablicy zawiera uin równy 0, a pozostałe pola są niezainicjowane. */
- GG_EVENT_NOTIFY_DESCR, /**< \brief Informacja o statusie opisowym osoby z listy kontaktów (przed 6.0). Zdarzenie należy obsługiwać, jeśli planuje się używać protokołu w wersji starszej niż domyślna. */
- GG_EVENT_STATUS, /**< \brief Zmiana statusu osoby z listy kontaktów (przed 6.0). Zdarzenie należy obsługiwać, jeśli planuje się używać protokołu w wersji starszej niż domyślna. */
- GG_EVENT_ACK, /**< Potwierdzenie doręczenia wiadomości */
- GG_EVENT_PONG, /**< \brief Utrzymanie połączenia. Obecnie serwer nie wysyła już do klienta ramek utrzymania połączenia, polega wyłącznie na wysyłaniu ramek przez klienta. */
- GG_EVENT_CONN_FAILED, /**< \brief Nie udało się połączyć */
- GG_EVENT_CONN_SUCCESS, /**< \brief Połączono z serwerem. Pierwszą rzeczą, jaką należy zrobić jest wysłanie listy kontaktów. */
- GG_EVENT_DISCONNECT, /**< \brief Serwer zrywa połączenie. Zdarza się, gdy równolegle do serwera podłączy się druga sesja i trzeba zerwać połączenie z pierwszą. */
- GG_EVENT_DCC_NEW, /**< Nowe połączenie bezpośrednie (6.x) */
- GG_EVENT_DCC_ERROR, /**< Błąd połączenia bezpośredniego (6.x) */
- GG_EVENT_DCC_DONE, /**< Zakończono połączenie bezpośrednie (6.x) */
- GG_EVENT_DCC_CLIENT_ACCEPT, /**< Moment akceptacji klienta w połączeniu bezpośrednim (6.x) */
- GG_EVENT_DCC_CALLBACK, /**< Zwrotne połączenie bezpośrednie (6.x) */
- GG_EVENT_DCC_NEED_FILE_INFO, /**< Należy wypełnić \c file_info dla połączenia bezpośredniego (6.x) */
- GG_EVENT_DCC_NEED_FILE_ACK, /**< Czeka na potwierdzenie pliku w połączeniu bezpośrednim (6.x) */
- GG_EVENT_DCC_NEED_VOICE_ACK, /**< Czeka na potwierdzenie rozmowy w połączeniu bezpośrednim (6.x) */
- GG_EVENT_DCC_VOICE_DATA, /**< Dane bezpośredniego połączenia głosowego (6.x) */
- GG_EVENT_PUBDIR50_SEARCH_REPLY, /**< Odpowiedź katalogu publicznego */
- GG_EVENT_PUBDIR50_READ, /**< Odczytano własne dane z katalogu publicznego */
- GG_EVENT_PUBDIR50_WRITE, /**< Zmieniono własne dane w katalogu publicznym */
- GG_EVENT_STATUS60, /**< Zmiana statusu osoby z listy kontaktów */
- GG_EVENT_NOTIFY60, /**< Informacja o statusach osób z listy kontaktów. Ostatni element tablicy zawiera uin równy 0, a pozostałe pola są niezainicjowane. */
- GG_EVENT_USERLIST, /**< Wynik importu lub eksportu listy kontaktów */
- GG_EVENT_IMAGE_REQUEST, /**< Żądanie przesłania obrazka z wiadomości */
- GG_EVENT_IMAGE_REPLY, /**< Przysłano obrazek z wiadomości */
- GG_EVENT_DCC_ACK, /**< Potwierdzenie transmisji w połączeniu bezpośrednim (6.x) */
- GG_EVENT_DCC7_NEW, /**< Nowe połączenie bezpośrednie (7.x) */
- GG_EVENT_DCC7_ACCEPT, /**< Zaakceptowano połączenie bezpośrednie (7.x), nowy deskryptor */
- GG_EVENT_DCC7_REJECT, /**< Odrzucono połączenie bezpośrednie (7.x) */
- GG_EVENT_DCC7_CONNECTED, /**< Zestawiono połączenie bezpośrednie (7.x), nowy deskryptor */
- GG_EVENT_DCC7_ERROR, /**< Błąd połączenia bezpośredniego (7.x) */
- GG_EVENT_DCC7_DONE, /**< Zakończono połączenie bezpośrednie (7.x) */
- GG_EVENT_DCC7_PENDING, /**< Trwa próba połączenia bezpośredniego (7.x), nowy deskryptor */
- GG_EVENT_XML_EVENT, /**< Otrzymano komunikat systemowy (7.7) */
- GG_EVENT_DISCONNECT_ACK, /**< \brief Potwierdzenie zakończenia sesji. Informuje o tym, że zmiana stanu na niedostępny z opisem dotarła do serwera i można zakończyć połączenie TCP. */
- GG_EVENT_TYPING_NOTIFICATION, /**< Powiadomienie o pisaniu */
- GG_EVENT_USER_DATA, /**< Informacja o kontaktach */
- GG_EVENT_MULTILOGON_MSG, /**< Wiadomość wysłana z innej sesji multilogowania */
- GG_EVENT_MULTILOGON_INFO, /**< Informacja o innych sesjach multilogowania */
- GG_EVENT_USERLIST100_VERSION, /**< Otrzymano numer wersji listy kontaktów na serwerze (10.0) */
- GG_EVENT_USERLIST100_REPLY, /**< Wynik importu lub eksportu listy kontaktów (10.0) */
- GG_EVENT_IMTOKEN, /**< Otrzymano ciąg IMTOKEN (11.0) */
- GG_EVENT_PONG110, /**< \brief Utrzymanie połączenia (11.0). Może służyć do synchronizacji czasu z serwerem. */
- GG_EVENT_JSON_EVENT, /**< Otrzymano komunikat systemowy (11.0) */
- GG_EVENT_ACK110, /**< Potwierdzenie wysłania wiadomości (11.0) */
- GG_EVENT_CHAT_INFO, /**< Otrzymano informację o konferencji (11.0). */
- GG_EVENT_CHAT_INFO_GOT_ALL, /**< \brief Informacje o wszystkich konferencjach zostały już wysłane (11.0). Otrzymywany po ostatnim pakiecie \c GG_EVENT_CHAT_INFO */
- GG_EVENT_CHAT_INFO_UPDATE, /**< \brief Aktualizacja informacji o konferencji (11.0). Dodanie, usunięcie jednego z uczestników. */
- GG_EVENT_CHAT_CREATED, /**< Potwierdzenie utworzenia konferencji (11.0) */
- GG_EVENT_CHAT_INVITE_ACK, /**< Potwierdzenie wysłania zaproszenia do konferencji (11.0) */
-#define GG_EVENT_SEARCH50_REPLY GG_EVENT_PUBDIR50_SEARCH_REPLY
- * Powód nieudanego połączenia.
- GG_FAILURE_RESOLVING = 1, /**< Nie znaleziono serwera */
- GG_FAILURE_CONNECTING, /**< Błąd połączenia */
- GG_FAILURE_INVALID, /**< Serwer zwrócił nieprawidłowe dane */
- GG_FAILURE_READING, /**< Zerwano połączenie podczas odczytu */
- GG_FAILURE_WRITING, /**< Zerwano połączenie podczas zapisu */
- GG_FAILURE_PASSWORD, /**< Nieprawidłowe hasło */
- GG_FAILURE_404, /**< Nieużywane */
- GG_FAILURE_TLS, /**< Błąd negocjacji szyfrowanego połączenia */
- GG_FAILURE_NEED_EMAIL, /**< Serwer rozłączył nas z prośbą o zmianę adresu e-mail */
- GG_FAILURE_INTRUDER, /**< Zbyt wiele prób połączenia z nieprawidłowym hasłem */
- GG_FAILURE_UNAVAILABLE, /**< Serwery są wyłączone */
- GG_FAILURE_PROXY, /**< Błąd serwera pośredniczącego */
- GG_FAILURE_HUB, /**< Błąd połączenia z hubem */
- GG_FAILURE_INTERNAL, /**< Błąd wewnętrzny */
- * Kod błędu danej operacji.
- * Nie zawiera przesadnie szczegółowych informacji o powodach błędów, by nie
- * komplikować ich obsługi. Jeśli wymagana jest większa dokładność, należy
- * sprawdzić zawartość zmiennej systemowej \c errno.
- GG_ERROR_RESOLVING = 1, /**< Nie znaleziono hosta */
- GG_ERROR_CONNECTING, /**< Błąd połączenia */
- GG_ERROR_READING, /**< Błąd odczytu/odbierania */
- GG_ERROR_WRITING, /**< Błąd zapisu/wysyłania */
- GG_ERROR_DCC_HANDSHAKE, /**< Błąd negocjacji */
- GG_ERROR_DCC_FILE, /**< Błąd odczytu/zapisu pliku */
- GG_ERROR_DCC_EOF, /**< Przedwczesny koniec pliku */
- GG_ERROR_DCC_NET, /**< Błąd wysyłania/odbierania */
- GG_ERROR_DCC_REFUSED, /**< Połączenie odrzucone */
- GG_ERROR_DCC7_HANDSHAKE, /**< Błąd negocjacji */
- GG_ERROR_DCC7_FILE, /**< Błąd odczytu/zapisu pliku */
- GG_ERROR_DCC7_EOF, /**< Przedwczesny koniec pliku */
- GG_ERROR_DCC7_NET, /**< Błąd wysyłania/odbierania */
- GG_ERROR_DCC7_REFUSED, /**< Połączenie odrzucone */
- GG_ERROR_DCC7_RELAY, /**< Problem z serwerem pośredniczącym */
- * Pole zapytania lub odpowiedzi katalogu publicznego.
-struct gg_pubdir50_entry {
- int num; /**< Numer wyniku */
- char *field; /**< Nazwa pola */
- char *value; /**< Wartość pola */
- * Zapytanie lub odpowiedź katalogu publicznego.
- * Patrz \c gg_pubdir50_t.
- int count; /**< Liczba wyników odpowiedzi */
- uin_t next; /**< Numer początkowy następnego zapytania */
- int type; /**< Rodzaj zapytania */
- uint32_t seq; /**< Numer sekwencyjny */
- struct gg_pubdir50_entry *entries; /**< Pola zapytania lub odpowiedzi */
- int entries_count; /**< Liczba pól */
- * Zapytanie lub odpowiedź katalogu publicznego.
- * Do pól nie należy się odwoływać bezpośrednio -- wszystkie niezbędne
- * informacje są dostępne za pomocą funkcji \c gg_pubdir50_*
-typedef struct gg_pubdir50_s *gg_pubdir50_t;
- * Opis zdarzeń \c GG_EVENT_MSG i \c GG_EVENT_MULTILOGON_MSG.
- uin_t sender; /**< Numer nadawcy/odbiorcy */
- int msgclass; /**< Klasa wiadomości */
- time_t time; /**< Czas nadania */
- uint32_t time; /**< Czas nadania */
- unsigned char *message; /**< Treść wiadomości */
- int recipients_count; /**< Liczba odbiorców konferencji */
- uin_t *recipients; /**< Odbiorcy konferencji */
- int formats_length; /**< Długość informacji o formatowaniu tekstu */
- void *formats; /**< Informacje o formatowaniu tekstu */
- uint32_t seq; /**< Numer sekwencyjny wiadomości */
- char *xhtml_message; /**< Treść wiadomości w formacie XHTML */
- uint64_t chat_id; /**< Identyfikator konferencji lub 0, jeżeli jest to zwykła wiadomość (11.0) */
- uint64_t flags; /**< Flagi wiadomości (11.0) */
- * Opis zdarzenia \c GG_EVENT_NOTIFY_DESCR.
-struct gg_event_notify_descr {
- struct gg_notify_reply *notify; /**< Informacje o liście kontaktów */
- char *descr; /**< Opis status */
- * Opis zdarzenia \c GG_EVENT_STATUS.
-struct gg_event_status {
- uin_t uin; /**< Numer Gadu-Gadu */
- uint32_t status; /**< Nowy status */
- char *descr; /**< Opis */
- * Opis zdarzenia \c GG_EVENT_STATUS60.
-struct gg_event_status60 {
- uin_t uin; /**< Numer Gadu-Gadu */
- int status; /**< Nowy status */
- uint32_t remote_ip; /**< Adres IP dla połączeń bezpośrednich */
- uint16_t remote_port; /**< Port dla połączeń bezpośrednich */
- int version; /**< Wersja protokołu */
- int image_size; /**< Maksymalny rozmiar obsługiwanych obrazków w KiB */
- char *descr; /**< Opis statusu */
- time_t time; /**< Czas powrotu */
- uint32_t time; /**< Czas powrotu */
- * Opis zdarzenia \c GG_EVENT_NOTIFY_REPLY60.
-struct gg_event_notify60 {
- uin_t uin; /**< Numer Gadu-Gadu. W ostatnim elemencie jest równy 0, a pozostałe pola są niezainicjowane. */
- int status; /**< Nowy status */
- uint32_t remote_ip; /**< Adres IP dla połączeń bezpośrednich */
- uint16_t remote_port; /**< Port dla połączeń bezpośrednich */
- int version; /**< Wersja protokołu */
- int image_size; /**< Maksymalny rozmiar obsługiwanych obrazków w KiB */
- char *descr; /**< Opis statusu */
- time_t time; /**< Czas powrotu */
- uint32_t time; /**< Czas powrotu */
- * Opis zdarzenia \c GG_EVENT_ACK.
- uin_t recipient; /**< Numer odbiorcy */
- int status; /**< Status doręczenia */
- int seq; /**< Numer sekwencyjny wiadomości */
- * Opis zdarzenia \c GG_EVENT_ACK110.
-struct gg_event_ack110 {
- uint8_t msg_type; /**< Rodzaj wiadomości (0x01 - zwykła, 0x02 - konferencja) */
- uint32_t seq; /**< Numer sekwencyjny */
- uint32_t time; /**< Czas zdarzenia */
- * Opis zdarzenia \c GG_EVENT_USERLIST.
-struct gg_event_userlist {
- char type; /**< Rodzaj odpowiedzi */
- char *reply; /**< Treść odpowiedzi */
- * Opis zdarzenia \c GG_EVENT_DCC_VOICE_DATA.
-struct gg_event_dcc_voice_data {
- uint8_t *data; /**< Dane dźwiękowe */
- int length; /**< Rozmiar danych dźwiękowych */
- * Opis zdarzenia \c GG_EVENT_IMAGE_REQUEST.
-struct gg_event_image_request {
- uin_t sender; /**< Nadawca żądania */
- uint32_t size; /**< Rozmiar obrazka */
- uint32_t crc32; /**< Suma kontrolna CRC32 */
- * Opis zdarzenia \c GG_EVENT_IMAGE_REPLY.
-struct gg_event_image_reply {
- uin_t sender; /**< Nadawca obrazka */
- uint32_t size; /**< Rozmiar obrazka */
- uint32_t crc32; /**< Suma kontrolna CRC32 */
- char *filename; /**< Nazwa pliku */
- char *image; /**< Bufor z obrazkiem */
- * Opis zdarzenia \c GG_EVENT_XML_EVENT.
-struct gg_event_xml_event {
- char *data; /**< Bufor z komunikatem */
- * Opis zdarzenia \c GG_EVENT_JSON_EVENT.
-struct gg_event_json_event {
- char *data; /**< Bufor z komunikatem */
- char *type; /**< Bufor z typem komunikatu */
- * Opis zdarzenia \c GG_EVENT_DCC7_CONNECTED.
-struct gg_event_dcc7_connected {
- struct gg_dcc7 *dcc7; /**< Struktura połączenia */
- * Opis zdarzenia \c GG_EVENT_DCC7_PENDING.
-struct gg_event_dcc7_pending {
- struct gg_dcc7 *dcc7; /**< Struktura połączenia */
- * Opis zdarzenia \c GG_EVENT_DCC7_REJECT.
-struct gg_event_dcc7_reject {
- struct gg_dcc7 *dcc7; /**< Struktura połączenia */
- int reason; /**< powód odrzucenia */
- * Opis zdarzenia \c GG_EVENT_DCC7_ACCEPT.
-struct gg_event_dcc7_accept {
- struct gg_dcc7 *dcc7; /**< Struktura połączenia */
- int type; /**< Sposób połączenia (P2P, przez serwer) */
- uint32_t remote_ip; /**< Adres zdalnego klienta */
- uint16_t remote_port; /**< Port zdalnego klienta */
- * Opis zdarzenia \c GG_EVENT_DCC7_DONE.
-struct gg_event_dcc7_done {
- struct gg_dcc7 *dcc7; /**< Struktura połączenia */
- * Opis zdarzenia \c GG_EVENT_TYPING_NOTIFICATION.
-struct gg_event_typing_notification {
- uin_t uin; /**< Numer rozmówcy */
- int length; /**< Długość tekstu */
-struct gg_event_user_data_attr {
- int type; /**< Typ atrybutu */
- char *key; /**< Klucz */
- char *value; /**< Wartość */
- * Struktura opisująca kontakt w zdarzeniu GG_EVENT_USER_DATA.
-struct gg_event_user_data_user {
- uin_t uin; /**< Numer kontaktu */
- size_t attr_count; /**< Liczba atrybutów */
- struct gg_event_user_data_attr *attrs; /**< Lista atrybutów */
- * Opis zdarzenia \c GG_EVENT_USER_DATA.
-struct gg_event_user_data {
- int type; /**< Rodzaj informacji o kontaktach */
- size_t user_count; /**< Liczba kontaktów */
- struct gg_event_user_data_user *users; /**< Lista kontaktów */
- * Struktura opisująca sesję multilogowania.
-struct gg_multilogon_session {
- gg_multilogon_id_t id; /**< Identyfikator sesji */
- char *name; /**< Nazwa sesji (podana w \c gg_login_params.client_version) */
- uint32_t remote_addr; /**< Adres sesji */
- int status_flags; /**< Flagi statusu sesji */
- int protocol_features; /**< Opcje protokolu sesji */
- time_t logon_time; /**< Czas zalogowania */
- uint32_t logon_time; /**< Czas zalogowania */
- * Opis zdarzenia \c GG_EVENT_MULTILOGON_INFO.
-struct gg_event_multilogon_info {
- int count; /**< Liczba sesji */
- struct gg_multilogon_session *sessions; /** Lista sesji */
- * Opis zdarzenia \c GG_EVENT_USERLIST100_VERSION.
-struct gg_event_userlist100_version {
- uint32_t version; /**< Numer wersji listy kontaktów na serwerze */
- * Opis zdarzenia \c GG_EVENT_USERLIST100_REPLY.
-struct gg_event_userlist100_reply {
- char type; /**< Rodzaj odpowiedzi */
- uint32_t version; /**< Aktualna wersja listy kontaktów na serwerze */
- char format_type; /**< Typ formatu listy kontaktów (żądany w \c gg_userlist100_request.format_type) */
- char *reply; /**< Treść listy kontaktów w przesyłanej wersji i formacie */
- * Opis zdarzenia \c GG_EVENT_IMTOKEN.
-struct gg_event_imtoken {
- char *imtoken; /**< Wartość IMTOKEN */
- * Opis zdarzenia \c GG_EVENT_PONG110.
-struct gg_event_pong110 {
- time_t time; /**< Aktualny czas na serwerze */
- uint32_t time; /**< Aktualny czas na serwerze */
- * Opis zdarzenia \c GG_EVENT_CHAT_INFO.
-struct gg_event_chat_info {
- uint64_t id; /**< Identyfikator konferencji */
- uint32_t version; /**< Wersja informacji o konferencji */
- uint32_t participants_count; /**< Ilość uczestników */
- uin_t *participants; /**< Lista uczestników */
- * Opis zdarzenia \c GG_EVENT_CHAT_INFO_UPDATE.
-struct gg_event_chat_info_update {
- uint64_t id; /**< Identyfikator konferencji */
- uint32_t type; /**< Typ aktualizacji (\c GG_CHAT_INFO_UPDATE_*) */
- uin_t participant; /**< Uczestnik, którego dotyczy aktualizacja */
- uin_t inviter; /**< Uczestnik inicjujący aktualizację (zapraszający) */
- uint32_t version; /**< Wersja informacji o konferencji */
- uint32_t time; /**< Czas zdarzenia */
- * Opis zdarzenia \c GG_EVENT_CHAT_CREATED.
-struct gg_event_chat_created {
- uint64_t id; /**< Identyfikator konferencji */
- uint32_t seq; /**< Numer sekwencyjny */
- * Opis zdarzenia \c GG_EVENT_CHAT_INVITE_ACK.
-struct gg_event_chat_invite_ack {
- uint64_t id; /**< Identyfikator konferencji */
- uint32_t seq; /**< Numer sekwencyjny */
- * Unia wszystkich zdarzeń zwracanych przez funkcje \c gg_watch_fd(),
- * \c gg_dcc_watch_fd() i \c gg_dcc7_watch_fd().
- enum gg_failure_t failure; /**< Błąd połączenia (\c GG_EVENT_CONN_FAILED) */
- struct gg_notify_reply *notify; /**< Zmiana statusu kontaktów (\c GG_EVENT_NOTIFY) */
- struct gg_event_notify_descr notify_descr; /**< Zmiana statusu kontaktów (\c GG_EVENT_NOTIFY_DESCR) */
- struct gg_event_status status; /**< Zmiana statusu kontaktów (\c GG_EVENT_STATUS) */
- struct gg_event_status60 status60; /**< Zmiana statusu kontaktów (\c GG_EVENT_STATUS60) */
- struct gg_event_notify60 *notify60; /**< Zmiana statusu kontaktów (\c GG_EVENT_NOTIFY60) */
- struct gg_event_msg msg; /**< Otrzymano wiadomość (\c GG_EVENT_MSG) */
- struct gg_event_ack ack; /**< Potwierdzenie wiadomości (\c GG_EVENT_ACK) */
- struct gg_event_ack110 ack110; /**< Potwierdzenie wysłania wiadomości (11.0) (\c GG_EVENT_ACK110) */
- struct gg_event_image_request image_request; /**< Żądanie wysłania obrazka (\c GG_EVENT_IMAGE_REQUEST) */
- struct gg_event_image_reply image_reply; /**< Odpowiedź z obrazkiem (\c GG_EVENT_IMAGE_REPLY) */
- struct gg_event_userlist userlist; /**< Odpowiedź listy kontaktów (\c GG_EVENT_USERLIST) */
- gg_pubdir50_t pubdir50; /**< Odpowiedź katalogu publicznego (\c GG_EVENT_PUBDIR50_*) */
- struct gg_event_xml_event xml_event; /**< Zdarzenie systemowe (\c GG_EVENT_XML_EVENT) */
- struct gg_event_json_event json_event; /**< Zdarzenie systemowe (\c GG_EVENT_JSON_EVENT) */
- struct gg_dcc *dcc_new; /**< Nowe połączenie bezpośrednie (\c GG_EVENT_DCC_NEW) */
- enum gg_error_t dcc_error; /**< Błąd połączenia bezpośredniego (\c GG_EVENT_DCC_ERROR) */
- struct gg_event_dcc_voice_data dcc_voice_data; /**< Dane połączenia głosowego (\c GG_EVENT_DCC_VOICE_DATA) */
- struct gg_dcc7 *dcc7_new; /**< Nowe połączenie bezpośrednie (\c GG_EVENT_DCC7_NEW) */
- enum gg_error_t dcc7_error; /**< Błąd połączenia bezpośredniego (\c GG_EVENT_DCC7_ERROR) */
- struct gg_event_dcc7_connected dcc7_connected; /**< Informacja o zestawieniu połączenia bezpośredniego (\c GG_EVENT_DCC7_CONNECTED) */
- struct gg_event_dcc7_pending dcc7_pending; /**< Trwa próba połączenia bezpośredniego (\c GG_EVENT_DCC7_PENDING) */
- struct gg_event_dcc7_reject dcc7_reject; /**< Odrzucono połączenia bezpośredniego (\c GG_EVENT_DCC7_REJECT) */
- struct gg_event_dcc7_accept dcc7_accept; /**< Zaakceptowano połączenie bezpośrednie (\c GG_EVENT_DCC7_ACCEPT) */
- struct gg_event_dcc7_done dcc7_done; /**< Zakończono połączenie bezpośrednie (\c GG_EVENT_DCC7_DONE) */
- struct gg_event_typing_notification typing_notification; /**< Powiadomienie o pisaniu */
- struct gg_event_user_data user_data; /**< Informacje o kontaktach */
- struct gg_event_msg multilogon_msg; /**< Inna sesja wysłała wiadomość (\c GG_EVENT_MULTILOGON_MSG) */
- struct gg_event_multilogon_info multilogon_info; /**< Informacja o innych sesjach multilogowania (\c GG_EVENT_MULTILOGON_INFO) */
- struct gg_event_userlist100_version userlist100_version; /**< Informacja o numerze wersji listy kontaktów na serwerze (\c GG_EVENT_USERLIST100_VERSION) */
- struct gg_event_userlist100_reply userlist100_reply; /**< Odpowiedź listy kontaktów (10.0) (\c GG_EVENT_USERLIST100_REPLY) */
- struct gg_event_imtoken imtoken; /**< Ciąg IMTOKEN (11.0) (\c GG_EVENT_IMTOKEN) */
- struct gg_event_pong110 pong110; /**< Utrzymanie połączenia (11.0) (\c GG_EVENT_PONG110) */
- struct gg_event_chat_info chat_info; /**< Informacje o konferencji (11.0) (\c GG_EVENT_CHAT_INFO) */
- struct gg_event_chat_info_update chat_info_update; /**< Aktualizacja informacji o konferencji (11.0) (\c GG_EVENT_CHAT_INFO_UPDATE) */
- struct gg_event_chat_created chat_created; /**< Potwierdzenie utworzenia konferencji (11.0) (\c GG_EVENT_CHAT_CREATED) */
- struct gg_event_chat_invite_ack chat_invite_ack; /**< Potwierdzenie wysłania zaproszenia do konferencji (11.0) (\c GG_EVENT_CHAT_INVITE_ACK) */
- * Zwracany przez funkcje \c gg_watch_fd(), \c gg_dcc_watch_fd()
- * i \c gg_dcc7_watch_fd(). Po przeanalizowaniu należy zwolnić
- * za pomocą \c gg_event_free().
- int type; /**< Rodzaj zdarzenia */
- union gg_event_union event; /**< Informacja o zdarzeniu */
-struct gg_event *gg_watch_fd(struct gg_session *sess);
-void gg_event_free(struct gg_event *e);
-int gg_notify_ex(struct gg_session *sess, uin_t *userlist, char *types, int count);
-int gg_notify(struct gg_session *sess, uin_t *userlist, int count);
-int gg_add_notify_ex(struct gg_session *sess, uin_t uin, char type);
-int gg_add_notify(struct gg_session *sess, uin_t uin);
-int gg_remove_notify_ex(struct gg_session *sess, uin_t uin, char type);
-int gg_remove_notify(struct gg_session *sess, uin_t uin);
-struct gg_http *gg_http_connect(const char *hostname, int port, int async, const char *method, const char *path, const char *header);
-int gg_http_watch_fd(struct gg_http *h);
-void gg_http_stop(struct gg_http *h);
-void gg_http_free(struct gg_http *h);
-uint32_t gg_pubdir50(struct gg_session *sess, gg_pubdir50_t req);
-gg_pubdir50_t gg_pubdir50_new(int type);
-int gg_pubdir50_add(gg_pubdir50_t req, const char *field, const char *value);
-int gg_pubdir50_seq_set(gg_pubdir50_t req, uint32_t seq);
-const char *gg_pubdir50_get(gg_pubdir50_t res, int num, const char *field);
-int gg_pubdir50_type(gg_pubdir50_t res);
-int gg_pubdir50_count(gg_pubdir50_t res);
-uin_t gg_pubdir50_next(gg_pubdir50_t res);
-uint32_t gg_pubdir50_seq(gg_pubdir50_t res);
-void gg_pubdir50_free(gg_pubdir50_t res);
-#define GG_PUBDIR50_UIN "FmNumber"
-#define GG_PUBDIR50_STATUS "FmStatus"
-#define GG_PUBDIR50_FIRSTNAME "firstname"
-#define GG_PUBDIR50_LASTNAME "lastname"
-#define GG_PUBDIR50_NICKNAME "nickname"
-#define GG_PUBDIR50_BIRTHYEAR "birthyear"
-#define GG_PUBDIR50_CITY "city"
-#define GG_PUBDIR50_GENDER "gender"
-#define GG_PUBDIR50_GENDER_FEMALE "1"
-#define GG_PUBDIR50_GENDER_MALE "2"
-#define GG_PUBDIR50_GENDER_SET_FEMALE "2"
-#define GG_PUBDIR50_GENDER_SET_MALE "1"
-#define GG_PUBDIR50_ACTIVE "ActiveOnly"
-#define GG_PUBDIR50_ACTIVE_TRUE "1"
-#define GG_PUBDIR50_START "fmstart"
-#define GG_PUBDIR50_FAMILYNAME "familyname"
-#define GG_PUBDIR50_FAMILYCITY "familycity"
- * Rodzaj pola zapytania.
- GG_PUBDIR50_UIN, /**< Numer Gadu-Gadu */
- GG_PUBDIR50_STATUS, /**< Status (tylko wynik wyszukiwania) */
- GG_PUBDIR50_FIRSTNAME, /**< Imię */
- GG_PUBDIR50_LASTNAME, /**< Nazwisko */
- GG_PUBDIR50_NICKNAME, /**< Pseudonim */
- GG_PUBDIR50_BIRTHYEAR, /**< Rok urodzenia lub przedział lat oddzielony spacją */
- GG_PUBDIR50_CITY, /**< Miejscowość */
- GG_PUBDIR50_GENDER, /**< Płeć */
- GG_PUBDIR50_ACTIVE, /**< Osoba dostępna (tylko wyszukiwanie) */
- GG_PUBDIR50_START, /**< Numer początkowy wyszukiwania (tylko wyszukiwanie) */
- GG_PUBDIR50_FAMILYNAME, /**< Nazwisko rodowe (tylko wysyłanie informacji o sobie) */
- GG_PUBDIR50_FAMILYCITY, /**< Miejscowość pochodzenia (tylko wysyłanie informacji o sobie) */
- * Wartość pola GG_PUBDIR50_GENDER przy wyszukiwaniu. Brak pola oznacza dowolną płeć.
- GG_PUBDIR50_GENDER_FEMALE, /**< Kobieta */
- GG_PUBDIR50_GENDER_MALE, /**< Mężczyzna */
- * Wartość pola GG_PUBDIR50_GENDER przy wysyłaniu informacji o sobie.
- GG_PUBDIR50_GENDER_SET_FEMALE, /**< Kobieta */
- GG_PUBDIR50_GENDER_SET_MALE, /**< Mężczyzna */
- * Wartość pola GG_PUBDIR50_ACTIVE.
- GG_PUBDIR50_ACTIVE_TRUE, /**< Wyszukaj tylko osoby dostępne */
- * Powód błędu operacji na katalogu publicznym.
- GG_PUBDIR_ERROR_NONE = 0, /**< Brak błędu */
- GG_PUBDIR_ERROR_OTHER, /**< Nieznany błąd */
- GG_PUBDIR_ERROR_TOKEN, /**< Błędny token */
- GG_PUBDIR_ERROR_OLD_PASSWORD, /**< Niepoprawne stare hasło */
- GG_PUBDIR_ERROR_NEW_PASSWORD, /**< Niepoprawne nowe hasło */
- * Wynik operacji na katalogu publicznym.
- int success; /**< Flaga powodzenia operacji */
- uin_t uin; /**< Otrzymany numer lub 0 w przypadku błędu */
- gg_pubdir_error_t error; /**< Powód błędu */
-int gg_pubdir_watch_fd(struct gg_http *f);
-void gg_pubdir_free(struct gg_http *f);
- * Token autoryzacji niektórych operacji HTTP.
- int width; /**< Szerokość obrazka */
- int height; /**< Wysokość obrazka */
- int length; /**< Liczba znaków w tokenie */
- char *tokenid; /**< Identyfikator tokenu */
-struct gg_http *gg_token(int async);
-int gg_token_watch_fd(struct gg_http *h);
-void gg_token_free(struct gg_http *h);
-struct gg_http *gg_register3(const char *email, const char *password, const char *tokenid, const char *tokenval, int async);
-#define gg_register_watch_fd gg_pubdir_watch_fd
-#define gg_register_free gg_pubdir_free
-struct gg_http *gg_unregister3(uin_t uin, const char *password, const char *tokenid, const char *tokenval, int async);
-#define gg_unregister_watch_fd gg_pubdir_watch_fd
-#define gg_unregister_free gg_pubdir_free
-struct gg_http *gg_remind_passwd3(uin_t uin, const char *email, const char *tokenid, const char *tokenval, int async);
-#define gg_remind_passwd_watch_fd gg_pubdir_watch_fd
-#define gg_remind_passwd_free gg_pubdir_free
-struct gg_http *gg_change_passwd4(uin_t uin, const char *email, const char *passwd, const char *newpasswd, const char *tokenid, const char *tokenval, int async);
-#define gg_change_passwd_watch_fd gg_pubdir_watch_fd
-#define gg_change_passwd_free gg_pubdir_free
-extern unsigned long gg_dcc_ip;
-int gg_dcc_request(struct gg_session *sess, uin_t uin);
-struct gg_dcc *gg_dcc_send_file(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin);
-struct gg_dcc *gg_dcc_get_file(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin);
-struct gg_dcc *gg_dcc_voice_chat(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin);
-void gg_dcc_set_type(struct gg_dcc *d, int type);
-int gg_dcc_fill_file_info(struct gg_dcc *d, const char *filename);
-int gg_dcc_fill_file_info2(struct gg_dcc *d, const char *filename, const char *local_filename);
-int gg_dcc_voice_send(struct gg_dcc *d, char *buf, int length);
-#define GG_DCC_VOICE_FRAME_LENGTH 195 /**< Rozmiar pakietu głosowego przed wersją Gadu-Gadu 5.0.5 */
-#define GG_DCC_VOICE_FRAME_LENGTH_505 326 /**< Rozmiar pakietu głosowego od wersji Gadu-Gadu 5.0.5 */
-struct gg_dcc *gg_dcc_socket_create(uin_t uin, uint16_t port);
-#define gg_dcc_socket_free gg_dcc_free
-#define gg_dcc_socket_watch_fd gg_dcc_watch_fd
-struct gg_event *gg_dcc_watch_fd(struct gg_dcc *d);
-void gg_dcc_free(struct gg_dcc *c);
-struct gg_event *gg_dcc7_watch_fd(struct gg_dcc7 *d);
-struct gg_dcc7 *gg_dcc7_send_file(struct gg_session *sess, uin_t rcpt, const char *filename, const char *filename1250, const char *hash);
-struct gg_dcc7 *gg_dcc7_send_file_fd(struct gg_session *sess, uin_t rcpt, int fd, size_t size, const char *filename1250, const char *hash);
-int gg_dcc7_accept(struct gg_dcc7 *dcc, unsigned int offset);
-int gg_dcc7_reject(struct gg_dcc7 *dcc, int reason);
-void gg_dcc7_free(struct gg_dcc7 *d);
-extern int gg_debug_level;
-extern void (*gg_debug_handler)(int level, const char *format, va_list ap);
-extern void (*gg_debug_handler_session)(struct gg_session *sess, int level, const char *format, va_list ap);
-extern FILE *gg_debug_file;
-#define GG_DEBUG_NET 1 /**< Rejestracja zdarzeń związanych z siecią */
-#define GG_DEBUG_TRAFFIC 2 /**< Rejestracja ruchu sieciowego */
-#define GG_DEBUG_DUMP 4 /**< Rejestracja zawartości pakietów */
-#define GG_DEBUG_FUNCTION 8 /**< Rejestracja wywołań funkcji */
-#define GG_DEBUG_MISC 16 /**< Rejestracja różnych informacji */
-#define GG_DEBUG_VERBOSE 32 /**< Rejestracja informacji szczegółowych */
-#define GG_DEBUG_WARNING 64 /**< Rejestracja ostrzeżeń */
-#define GG_DEBUG_ERROR 128 /**< Rejestracja błędów krytycznych */
-const char *gg_debug_state(enum gg_state_t state);
-const char *gg_debug_event(enum gg_event_t event);
-#define gg_debug(...) do { } while (0)
-#define gg_debug_session(...) do { } while (0)
-void gg_debug(int level, const char *format, ...) GG_GNUC_PRINTF(2, 3);
-void gg_debug_session(struct gg_session *sess, int level, const char *format, ...) GG_GNUC_PRINTF(3, 4);
-const char *gg_libgadu_version(void);
- * Lista funkcji biblioteki, które zależą od zewnętrznych bibliotek.
- GG_LIBGADU_FEATURE_SSL, /**< Biblioteka obsługuje połączenia szyfrowane */
- GG_LIBGADU_FEATURE_PTHREAD, /**< Biblioteka obsługuje rozwiązywanie nazw za pomocą wątków */
- GG_LIBGADU_FEATURE_USERLIST100, /**< Biblioteka obsługuje listę kontaktów zgodną z Gadu-Gadu 10 */
-int gg_libgadu_check_feature(gg_libgadu_feature_t feature);
-extern int gg_proxy_enabled;
-extern char *gg_proxy_host;
-extern int gg_proxy_port;
-extern char *gg_proxy_username;
-extern char *gg_proxy_password;
-extern int gg_proxy_http_only;
-extern unsigned long gg_local_ip;
-#define GG_LOGIN_HASH_GG32 0x01 /**< Algorytm Gadu-Gadu */
-#define GG_LOGIN_HASH_SHA1 0x02 /**< Algorytm SHA1 */
-#define GG_PUBDIR50_WRITE 0x01
-#define GG_PUBDIR50_READ 0x02
-#define GG_PUBDIR50_SEARCH 0x03
-#define GG_PUBDIR50_SEARCH_REQUEST GG_PUBDIR50_SEARCH
-#define GG_PUBDIR50_SEARCH_REPLY 0x05
- * Rodzaj zapytania lub odpowiedzi katalogu publicznego.
- GG_PUBDIR50_WRITE, /**< Wysłanie do serwera informacji o sobie */
- GG_PUBDIR50_READ, /**< Pobranie z serwera informacji o sobie */
- GG_PUBDIR50_SEARCH, /**< Wyszukiwanie w katalogu publicznym */
- GG_PUBDIR50_SEARCH_REPLY, /**< Wynik wyszukiwania w katalogu publicznym */
-#define gg_free_event gg_event_free
-#define gg_free_http gg_http_free
-#define gg_free_pubdir gg_pubdir_free
-#define gg_free_register gg_pubdir_free
-#define gg_free_remind_passwd gg_pubdir_free
-#define gg_free_dcc gg_dcc_free
-#define gg_free_change_passwd gg_pubdir_free
-struct gg_search_request {
- struct gg_search_result *results;
-struct gg_search_result {
-#define GG_GENDER_NONE 0
-#define GG_GENDER_FEMALE 1
-#define GG_GENDER_MALE 2
-struct gg_http *gg_search(const struct gg_search_request *r, int async) GG_DEPRECATED;
-int gg_search_watch_fd(struct gg_http *f) GG_DEPRECATED;
-void gg_free_search(struct gg_http *f) GG_DEPRECATED;
-#define gg_search_free gg_free_search
-const struct gg_search_request *gg_search_request_mode_0(char *nickname, char *first_name, char *last_name, char *city, int gender, int min_birth, int max_birth, int active, int start) GG_DEPRECATED;
-const struct gg_search_request *gg_search_request_mode_1(char *email, int active, int start) GG_DEPRECATED;
-const struct gg_search_request *gg_search_request_mode_2(char *phone, int active, int start) GG_DEPRECATED;
-const struct gg_search_request *gg_search_request_mode_3(uin_t uin, int active, int start) GG_DEPRECATED;
-void gg_search_request_free(struct gg_search_request *r) GG_DEPRECATED;
-struct gg_http *gg_register(const char *email, const char *password, int async) GG_DEPRECATED;
-struct gg_http *gg_register2(const char *email, const char *password, const char *qa, int async) GG_DEPRECATED;
-struct gg_http *gg_unregister(uin_t uin, const char *password, const char *email, int async) GG_DEPRECATED;
-struct gg_http *gg_unregister2(uin_t uin, const char *password, const char *qa, int async) GG_DEPRECATED;
-struct gg_http *gg_remind_passwd(uin_t uin, int async) GG_DEPRECATED;
-struct gg_http *gg_remind_passwd2(uin_t uin, const char *tokenid, const char *tokenval, int async) GG_DEPRECATED;
-struct gg_http *gg_change_passwd(uin_t uin, const char *passwd, const char *newpasswd, const char *newemail, int async) GG_DEPRECATED;
-struct gg_http *gg_change_passwd2(uin_t uin, const char *passwd, const char *newpasswd, const char *email, const char *newemail, int async) GG_DEPRECATED;
-struct gg_http *gg_change_passwd3(uin_t uin, const char *passwd, const char *newpasswd, const char *qa, int async) GG_DEPRECATED;
-struct gg_change_info_request {
-struct gg_change_info_request *gg_change_info_request_new(const char *first_name, const char *last_name, const char *nickname, const char *email, int born, int gender, const char *city) GG_DEPRECATED;
-void gg_change_info_request_free(struct gg_change_info_request *r) GG_DEPRECATED;
-struct gg_http *gg_change_info(uin_t uin, const char *passwd, const struct gg_change_info_request *request, int async) GG_DEPRECATED;
-#define gg_change_pubdir_watch_fd gg_pubdir_watch_fd
-#define gg_change_pubdir_free gg_pubdir_free
-#define gg_free_change_pubdir gg_pubdir_free
-struct gg_http *gg_userlist_get(uin_t uin, const char *password, int async) GG_DEPRECATED;
-int gg_userlist_get_watch_fd(struct gg_http *f) GG_DEPRECATED;
-void gg_userlist_get_free(struct gg_http *f) GG_DEPRECATED;
-struct gg_http *gg_userlist_put(uin_t uin, const char *password, const char *contacts, int async) GG_DEPRECATED;
-int gg_userlist_put_watch_fd(struct gg_http *f) GG_DEPRECATED;
-void gg_userlist_put_free(struct gg_http *f) GG_DEPRECATED;
-struct gg_http *gg_userlist_remove(uin_t uin, const char *password, int async) GG_DEPRECATED;
-int gg_userlist_remove_watch_fd(struct gg_http *f) GG_DEPRECATED;
-void gg_userlist_remove_free(struct gg_http *f) GG_DEPRECATED;
-int gg_pubdir50_handle_reply(struct gg_event *e, const char *packet, int length) GG_DEPRECATED;
-int gg_file_hash_sha1(int fd, uint8_t *result) GG_DEPRECATED;
-char *gg_saprintf(const char *format, ...) GG_GNUC_PRINTF(1, 2) GG_DEPRECATED;
-char *gg_vsaprintf(const char *format, va_list ap) GG_DEPRECATED;
-#define gg_alloc_sprintf gg_saprintf
-char *gg_get_line(char **ptr) GG_DEPRECATED;
-int gg_connect(void *addr, int port, int async) GG_DEPRECATED;
-struct in_addr *gg_gethostbyname(const char *hostname) GG_DEPRECATED;
-char *gg_read_line(int sock, char *buf, int length) GG_DEPRECATED;
-void gg_chomp(char *line) GG_DEPRECATED;
-char *gg_urlencode(const char *str) GG_DEPRECATED;
-int gg_http_hash(const char *format, ...) GG_DEPRECATED;
-void gg_http_free_fields(struct gg_http *h) GG_DEPRECATED;
-int gg_read(struct gg_session *sess, char *buf, int length) GG_DEPRECATED;
-int gg_write(struct gg_session *sess, const char *buf, int length) GG_DEPRECATED;
-void *gg_recv_packet(struct gg_session *sess) GG_DEPRECATED;
-int gg_send_packet(struct gg_session *sess, int type, ...) GG_DEPRECATED;
-unsigned int gg_login_hash(const unsigned char *password, unsigned int seed) GG_DEPRECATED;
-void gg_login_hash_sha1(const char *password, uint32_t seed, uint8_t *result) GG_DEPRECATED;
-uint32_t gg_fix32(uint32_t x);
-uint16_t gg_fix16(uint16_t x);
-char *gg_proxy_auth(void) GG_DEPRECATED;
-char *gg_base64_encode(const char *buf) GG_DEPRECATED;
-char *gg_base64_decode(const char *buf) GG_DEPRECATED;
-int gg_image_queue_remove(struct gg_session *s, struct gg_image_queue *q, int freeq) GG_DEPRECATED;
- * Kolejka odbieranych obrazków.
- uin_t sender; /**< Nadawca obrazka */
- uint32_t size; /**< Rozmiar obrazka */
- uint32_t crc32; /**< Suma kontrolna CRC32 */
- char *filename; /**< Nazwa pliku */
- char *image; /**< Bufor z odebranymi danymi */
- uint32_t done; /**< Rozmiar odebranych danych */
- struct gg_image_queue *next; /**< Kolejny element listy */
- uint32_t packet_type; /**< \brief Rodzaj odbieranych pakietów. W niektórych przypadkach (przy multilogowaniu) serwer wysyła nam dwie kopie obrazka jako dwa różne typy pakietów */
-int gg_dcc7_handle_id(struct gg_session *sess, struct gg_event *e, const void *payload, int len) GG_DEPRECATED;
-int gg_dcc7_handle_new(struct gg_session *sess, struct gg_event *e, const void *payload, int len) GG_DEPRECATED;
-int gg_dcc7_handle_info(struct gg_session *sess, struct gg_event *e, const void *payload, int len) GG_DEPRECATED;
-int gg_dcc7_handle_accept(struct gg_session *sess, struct gg_event *e, const void *payload, int len) GG_DEPRECATED;
-int gg_dcc7_handle_reject(struct gg_session *sess, struct gg_event *e, const void *payload, int len) GG_DEPRECATED;
-#define GG_APPMSG_HOST "appmsg.gadu-gadu.pl"
-#define GG_APPMSG_PORT 80
-#define GG_PUBDIR_HOST "pubdir.gadu-gadu.pl"
-#define GG_PUBDIR_PORT 80
-#define GG_REGISTER_HOST "register.gadu-gadu.pl"
-#define GG_REGISTER_PORT 80
-#define GG_REMIND_HOST "retr.gadu-gadu.pl"
-#define GG_REMIND_PORT 80
-#define GG_RELAY_HOST "relay.gadu-gadu.pl"
-#define GG_RELAY_PORT 80
-#define GG_DEFAULT_PORT 8074
-#define GG_HTTPS_PORT 443
-#define GG_HTTP_USERAGENT "Mozilla/4.7 [en] (Win98; I)"
-#define GG_PROTOCOL_VERSION_100 0x2e
-#define GG_PROTOCOL_VERSION_110 0x40
-#define GG_DEFAULT_CLIENT_VERSION "-"
-#define GG_DEFAULT_PROTOCOL_VERSION GG_PROTOCOL_VERSION_110
-#define GG_DEFAULT_TIMEOUT 30
-#define GG_HAS_AUDIO_MASK 0x40000000
-#define GG_HAS_AUDIO7_MASK 0x20000000
-#define GG_ERA_OMNIX_MASK 0x04000000
-#undef GG_LIBGADU_VERSION
-#define GG_FEATURE_MSG77 0x0001
-#define GG_FEATURE_STATUS77 0x0002
-#define GG_FEATURE_UNKNOWN_4 0x0004
-#define GG_FEATURE_UNKNOWN_8 0x0008
-#define GG_FEATURE_DND_FFC 0x0010
-#define GG_FEATURE_IMAGE_DESCR 0x0020
-#define GG_FEATURE_UNKNOWN_40 0x0040
-#define GG_FEATURE_UNKNOWN_80 0x0080
-#define GG_FEATURE_UNKNOWN_100 0x0100
-#define GG_FEATURE_USER_DATA 0x0200
-#define GG_FEATURE_MSG_ACK 0x0400
-#define GG_FEATURE_UNKNOWN_800 0x0800
-#define GG_FEATURE_UNKNOWN_1000 0x1000
-#define GG_FEATURE_TYPING_NOTIFICATION 0x2000
-#define GG_FEATURE_MULTILOGON 0x4000
-/* Poniższe makra zostały zachowane dla zgodności API */
-#define GG_FEATURE_MSG80 0
-#define GG_FEATURE_STATUS80 0
-#define GG_FEATURE_STATUS80BETA 0
-#define GG_FEATURE_ALL (GG_FEATURE_MSG80 | GG_FEATURE_STATUS80 | GG_FEATURE_DND_FFC | GG_FEATURE_IMAGE_DESCR | GG_FEATURE_UNKNOWN_100 | GG_FEATURE_USER_DATA | GG_FEATURE_MSG_ACK | GG_FEATURE_TYPING_NOTIFICATION)
- * Flagi opcji protokołu.
- GG_FEATURE_MSG77, /**< Klient życzy sobie otrzymywać wiadomości zgodnie z protokołem 7.7 */
- GG_FEATURE_STATUS77, /**< Klient życzy sobie otrzymywać zmiany stanu zgodnie z protokołem 7.7 */
- GG_FEATURE_DND_FFC, /**< Klient obsługuje statusy "nie przeszkadzać" i "poGGadaj ze mną" */
- GG_FEATURE_IMAGE_DESCR, /**< Klient obsługuje opisy graficzne oraz flagę \c GG_STATUS80_DESCR_MASK */
-#define GG_DEFAULT_DCC_PORT 1550
- uint32_t type; /* typ pakietu */
- uint32_t length; /* długość reszty pakietu */
-#define GG_WELCOME 0x0001
-#define GG_NEED_EMAIL 0x0014
- uint32_t key; /* klucz szyfrowania hasła */
- uint32_t uin; /* mój numerek */
- uint32_t hash; /* hash hasła */
- uint32_t status; /* status na dzień dobry */
- uint32_t version; /* moja wersja klienta */
- uint32_t local_ip; /* mój adres ip */
- uint16_t local_port; /* port, na którym słucham */
-#define GG_LOGIN_EXT 0x0013
- uint32_t uin; /* mój numerek */
- uint32_t hash; /* hash hasła */
- uint32_t status; /* status na dzień dobry */
- uint32_t version; /* moja wersja klienta */
- uint32_t local_ip; /* mój adres ip */
- uint16_t local_port; /* port, na którym słucham */
- uint32_t external_ip; /* zewnętrzny adres ip */
- uint16_t external_port; /* zewnętrzny port */
-#define GG_LOGIN60 0x0015
- uint32_t uin; /* mój numerek */
- uint32_t hash; /* hash hasła */
- uint32_t status; /* status na dzień dobry */
- uint32_t version; /* moja wersja klienta */
- uint8_t dunno1; /* 0x00 */
- uint32_t local_ip; /* mój adres ip */
- uint16_t local_port; /* port, na którym słucham */
- uint32_t external_ip; /* zewnętrzny adres ip */
- uint16_t external_port; /* zewnętrzny port */
- uint8_t image_size; /* maksymalny rozmiar grafiki w KiB */
- uint8_t dunno2; /* 0xbe */
-#define GG_LOGIN70 0x0019
- uint32_t uin; /* mój numerek */
- uint8_t hash_type; /* rodzaj hashowania hasła */
- uint8_t hash[64]; /* hash hasła dopełniony zerami */
- uint32_t status; /* status na dzień dobry */
- uint32_t version; /* moja wersja klienta */
- uint8_t dunno1; /* 0x00 */
- uint32_t local_ip; /* mój adres ip */
- uint16_t local_port; /* port, na którym słucham */
- uint32_t external_ip; /* zewnętrzny adres ip (???) */
- uint16_t external_port; /* zewnętrzny port (???) */
- uint8_t image_size; /* maksymalny rozmiar grafiki w KiB */
- uint8_t dunno2; /* 0xbe */
-#define GG_LOGIN_OK 0x0003
-#define GG_LOGIN_FAILED 0x0009
-#define GG_PUBDIR50_REQUEST 0x0014
-struct gg_pubdir50_request {
- uint8_t type; /* GG_PUBDIR50_* */
- uint32_t seq; /* czas wysłania zapytania */
-#define GG_PUBDIR50_REPLY 0x000e
-struct gg_pubdir50_reply {
- uint8_t type; /* GG_PUBDIR50_* */
- uint32_t seq; /* czas wysłania zapytania */
-#define GG_NEW_STATUS 0x0002
-#define GG_STATUS_NOT_AVAIL 0x0001
-#define GG_STATUS_NOT_AVAIL_DESCR 0x0015
-#define GG_STATUS_FFC 0x0017
-#define GG_STATUS_FFC_DESCR 0x0018
-#define GG_STATUS_AVAIL 0x0002
-#define GG_STATUS_AVAIL_DESCR 0x0004
-#define GG_STATUS_BUSY 0x0003
-#define GG_STATUS_BUSY_DESCR 0x0005
-#define GG_STATUS_DND 0x0021
-#define GG_STATUS_DND_DESCR 0x0022
-#define GG_STATUS_INVISIBLE 0x0014
-#define GG_STATUS_INVISIBLE_DESCR 0x0016
-#define GG_STATUS_BLOCKED 0x0006
-#define GG_STATUS_GGPLUS 0x0020
-#define GG_STATUS_NOT_SET 0x0023
-#define GG_STATUS_UNKNOWN 0x0025
-#define GG_STATUS_IMAGE_MASK 0x0100
-#define GG_STATUS_DESCR_MASK 0x4000
-#define GG_STATUS_FRIENDS_MASK 0x8000
-#define GG_STATUS_FLAG_UNKNOWN 0x00000001
-#define GG_STATUS_FLAG_VIDEO 0x00000002
-#define GG_STATUS_FLAG_INHERIT 0x00000020
-#define GG_STATUS_FLAG_MOBILE 0x00100000
-#define GG_STATUS_FLAG_SPAM 0x00800000
- * Rodzaje statusów użytkownika.
- GG_STATUS_NOT_AVAIL, /**< Niedostępny */
- GG_STATUS_NOT_AVAIL_DESCR, /**< Niedostępny z opisem */
- GG_STATUS_FFC, /**< PoGGadaj ze mną */
- GG_STATUS_FFC_DESCR, /**< PoGGadaj ze mną z opisem */
- GG_STATUS_AVAIL, /**< Dostępny */
- GG_STATUS_AVAIL_DESCR, /**< Dostępny z opisem */
- GG_STATUS_BUSY, /**< Zajęty */
- GG_STATUS_BUSY_DESCR, /**< Zajęty z opisem */
- GG_STATUS_DND, /**< Nie przeszkadzać */
- GG_STATUS_DND_DESCR, /**< Nie przeszakdzać z opisem */
- GG_STATUS_INVISIBLE, /**< Niewidoczny (tylko własny status) */
- GG_STATUS_INVISIBLE_DESCR, /**< Niewidoczny z opisem (tylko własny status) */
- GG_STATUS_BLOCKED, /**< Zablokowany (tylko status innych) */
- GG_STATUS_GGPLUS, /**< Status "Korzystam z GG Plus" */
- GG_STATUS_NOT_SET, /**< Status nie ustawiony (przy logowaniu się do sieci) */
- GG_STATUS_IMAGE_MASK, /**< Flaga bitowa oznaczająca opis graficzny (tylko jeśli wybrano \c GG_FEATURE_IMAGE_DESCR) */
- GG_STATUS_DESCR_MASK, /**< Flaga bitowa oznaczająca status z opisem (tylko jeśli wybrano \c GG_FEATURE_IMAGE_DESCR) */
- GG_STATUS_FRIENDS_MASK, /**< Flaga bitowa dostępności tylko dla znajomych */
- * Rodzaje statusów użytkownika. Mapa bitowa.
- GG_STATUS_FLAG_UNKNOWN, /**< Przeznaczenie nieznane, ale występuje zawsze */
- GG_STATUS_FLAG_VIDEO, /**< Klient obsługuje wideorozmowy */
- GG_STATUS_FLAG_INHERIT, /**< Synchronizacja statusu do innych klientów (przy logowaniu się do sieci) */
- GG_STATUS_FLAG_MOBILE, /**< Klient mobilny (ikona telefonu komórkowego) */
- GG_STATUS_FLAG_SPAM, /**< Klient chce otrzymywać linki od nieznajomych */
- * Flaga bitowa dostepnosci informujaca ze mozemy voipowac
-#define GG_STATUS_VOICE_MASK 0x20000 /**< czy ma wlaczone audio (7.7) */
- * Maksymalna długośc opisu.
-#define GG_STATUS_DESCR_MAXSIZE 255
-#define GG_STATUS_DESCR_MAXSIZE_PRE_8_0 70
-#define GG_STATUS_MASK 0xff
-/* GG_S_F() tryb tylko dla znajomych */
-#define GG_S_F(x) (((x) & GG_STATUS_FRIENDS_MASK) != 0)
-/* GG_S() stan bez uwzględnienia dodatkowych flag */
-#define GG_S(x) ((x) & GG_STATUS_MASK)
-/* GG_S_FF() chętny do rozmowy */
-#define GG_S_FF(x) (GG_S(x) == GG_STATUS_FFC || GG_S(x) == GG_STATUS_FFC_DESCR)
-/* GG_S_AV() dostępny */
-#define GG_S_AV(x) (GG_S(x) == GG_STATUS_AVAIL || GG_S(x) == GG_STATUS_AVAIL_DESCR)
-/* GG_S_AW() zaraz wracam */
-#define GG_S_AW(x) (GG_S(x) == GG_STATUS_BUSY || GG_S(x) == GG_STATUS_BUSY_DESCR)
-/* GG_S_DD() nie przeszkadzać */
-#define GG_S_DD(x) (GG_S(x) == GG_STATUS_DND || GG_S(x) == GG_STATUS_DND_DESCR)
-/* GG_S_NA() niedostępny */
-#define GG_S_NA(x) (GG_S(x) == GG_STATUS_NOT_AVAIL || GG_S(x) == GG_STATUS_NOT_AVAIL_DESCR)
-/* GG_S_I() niewidoczny */
-#define GG_S_I(x) (GG_S(x) == GG_STATUS_INVISIBLE || GG_S(x) == GG_STATUS_INVISIBLE_DESCR)
-/* GG_S_A() dostępny lub chętny do rozmowy */
-#define GG_S_A(x) (GG_S_FF(x) || GG_S_AV(x))
-/* GG_S_B() zajęty lub nie przeszkadzać */
-#define GG_S_B(x) (GG_S_AW(x) || GG_S_DD(x))
-/* GG_S_D() stan opisowy */
-#define GG_S_D(x) (GG_S(x) == GG_STATUS_NOT_AVAIL_DESCR || \
- GG_S(x) == GG_STATUS_FFC_DESCR || \
- GG_S(x) == GG_STATUS_AVAIL_DESCR || \
- GG_S(x) == GG_STATUS_BUSY_DESCR || \
- GG_S(x) == GG_STATUS_DND_DESCR || \
- GG_S(x) == GG_STATUS_INVISIBLE_DESCR)
-/* GG_S_BL() blokowany lub blokujący */
-#define GG_S_BL(x) (GG_S(x) == GG_STATUS_BLOCKED)
- * Zmiana statusu (pakiet \c GG_NEW_STATUS i \c GG_NEW_STATUS80BETA)
- uint32_t status; /**< Nowy status */
-#define GG_NOTIFY_FIRST 0x000f
-#define GG_NOTIFY_LAST 0x0010
-#define GG_NOTIFY 0x0010
- uint32_t uin; /* numerek danej osoby */
- uint8_t dunno1; /* rodzaj wpisu w liście */
-#define GG_USER_OFFLINE 0x01
-#define GG_USER_NORMAL 0x03
-#define GG_USER_BLOCKED 0x04
- GG_USER_NORMAL, /**< Zwykły kontakt */
- GG_USER_BLOCKED, /**< Zablokowany */
- GG_USER_OFFLINE, /**< Niewidoczny dla kontaktu */
-#define GG_LIST_EMPTY 0x0012
-#define GG_NOTIFY_REPLY 0x000c /* tak, to samo co GG_LOGIN */
-struct gg_notify_reply {
- uint32_t uin; /* numerek */
- uint32_t status; /* status danej osoby */
- uint32_t remote_ip; /* adres ip delikwenta */
- uint16_t remote_port; /* port, na którym słucha klient */
- uint32_t version; /* wersja klienta */
- uint16_t dunno2; /* znowu port? */
-#define GG_NOTIFY_REPLY60 0x0011
-struct gg_notify_reply60 {
- uint32_t uin; /* numerek plus flagi w MSB */
- uint8_t status; /* status danej osoby */
- uint32_t remote_ip; /* adres ip delikwenta */
- uint16_t remote_port; /* port, na którym słucha klient */
- uint8_t version; /* wersja klienta */
- uint8_t image_size; /* maksymalny rozmiar grafiki w KiB */
- uint8_t dunno1; /* 0x00 */
-#define GG_STATUS60 0x000f
- uint32_t uin; /* numerek plus flagi w MSB */
- uint8_t status; /* status danej osoby */
- uint32_t remote_ip; /* adres ip delikwenta */
- uint16_t remote_port; /* port, na którym słucha klient */
- uint8_t version; /* wersja klienta */
- uint8_t image_size; /* maksymalny rozmiar grafiki w KiB */
- uint8_t dunno1; /* 0x00 */
-#define GG_NOTIFY_REPLY77 0x0018
-struct gg_notify_reply77 {
- uint32_t uin; /* numerek plus flagi w MSB */
- uint8_t status; /* status danej osoby */
- uint32_t remote_ip; /* adres ip delikwenta */
- uint16_t remote_port; /* port, na którym słucha klient */
- uint8_t version; /* wersja klienta */
- uint8_t image_size; /* maksymalny rozmiar grafiki w KiB */
- uint8_t dunno1; /* 0x00 */
- uint32_t dunno2; /* ? */
-#define GG_STATUS77 0x0017
- uint32_t uin; /* numerek plus flagi w MSB */
- uint8_t status; /* status danej osoby */
- uint32_t remote_ip; /* adres ip delikwenta */
- uint16_t remote_port; /* port, na którym słucha klient */
- uint8_t version; /* wersja klienta */
- uint8_t image_size; /* maksymalny rozmiar grafiki w KiB */
- uint8_t dunno1; /* 0x00 */
- uint32_t dunno2; /* ? */
-#define GG_ADD_NOTIFY 0x000d
-#define GG_REMOVE_NOTIFY 0x000e
- uint32_t uin; /* numerek */
- uint8_t dunno1; /* bitmapa */
-#define GG_STATUS 0x0002
- uint32_t uin; /* numerek */
- uint32_t status; /* nowy stan */
-#define GG_SEND_MSG 0x000b
-#define GG_CLASS_QUEUED 0x0001
-#define GG_CLASS_OFFLINE GG_CLASS_QUEUED
-#define GG_CLASS_MSG 0x0004
-#define GG_CLASS_CHAT 0x0008
-#define GG_CLASS_CTCP 0x0010
-#define GG_CLASS_ACK 0x0020
-#define GG_CLASS_EXT GG_CLASS_ACK /**< Dla kompatybilności wstecz */
- * Klasy wiadomości. Wartości są maskami bitowymi, które w większości
- * przypadków można łączyć (połączenie \c GG_CLASS_MSG i \c GG_CLASS_CHAT
- GG_CLASS_MSG, /**< Wiadomość ma pojawić się w osobnym oknie */
- GG_CLASS_CHAT, /**< Wiadomość ma pojawić się w oknie rozmowy */
- GG_CLASS_CTCP, /**< Wiadomość przeznaczona dla klienta Gadu-Gadu */
- GG_CLASS_ACK, /**< Klient nie życzy sobie potwierdzenia */
- GG_CLASS_QUEUED, /**< Wiadomość zakolejkowana na serwerze (tylko przy odbieraniu) */
- * Maksymalna długość wiadomości.
-#define GG_MSG_MAXSIZE 1989
-struct gg_msg_richtext {
- * Struktura opisująca formatowanie tekstu. W zależności od wartości pola
- * \c font, zaraz za tą strukturą może wystąpić \c gg_msg_richtext_color
- * lub \c gg_msg_richtext_image.
-struct gg_msg_richtext_format {
- uint16_t position; /**< Początkowy znak formatowania (liczony od 0) */
- uint8_t font; /**< Atrybuty formatowania */
-#define GG_FONT_BOLD 0x01
-#define GG_FONT_ITALIC 0x02
-#define GG_FONT_UNDERLINE 0x04
-#define GG_FONT_COLOR 0x08
-#define GG_FONT_IMAGE 0x80
- * Atrybuty formatowania wiadomości.
- * Struktura opisującą kolor tekstu dla atrybutu \c GG_FONT_COLOR.
-struct gg_msg_richtext_color {
- uint8_t red; /**< Składowa czerwona koloru */
- uint8_t green; /**< Składowa zielona koloru */
- uint8_t blue; /**< Składowa niebieska koloru */
- * Strukturya opisująca obrazek wstawiony do wiadomości dla atrubutu
-struct gg_msg_richtext_image {
- uint16_t unknown1; /**< Nieznane pole o wartości 0x0109 */
- uint32_t size; /**< Rozmiar obrazka */
- uint32_t crc32; /**< Suma kontrolna CRC32 obrazka */
-struct gg_msg_recipients {
-struct gg_msg_image_request {
-struct gg_msg_image_reply {
-#define GG_SEND_MSG_ACK 0x0005
-#define GG_ACK_BLOCKED 0x0001
-#define GG_ACK_DELIVERED 0x0002
-#define GG_ACK_QUEUED 0x0003
-#define GG_ACK_MBOXFULL 0x0004
-#define GG_ACK_NOT_DELIVERED 0x0006
- * Status doręczenia wiadomości.
- GG_ACK_DELIVERED, /**< Wiadomość dostarczono. */
- GG_ACK_QUEUED, /**< Wiadomość zakolejkowano z powodu niedostępności odbiorcy. */
- GG_ACK_BLOCKED, /**< Wiadomość zablokowana przez serwer (spam, świąteczne ograniczenia itd.) */
- GG_ACK_MBOXFULL, /**< Wiadomości nie dostarczono z powodu zapełnionej kolejki wiadomości odbiorcy. */
- GG_ACK_NOT_DELIVERED /**< Wiadomości nie dostarczono (tylko dla \c GG_CLASS_CTCP). */
-struct gg_send_msg_ack {
-#define GG_RECV_MSG 0x000a
-#define GG_DISCONNECTING 0x000b
-#define GG_USERLIST_REQUEST 0x0016
-#define GG_XML_EVENT 0x0027
-#define GG_USERLIST_PUT 0x00
-#define GG_USERLIST_PUT_MORE 0x01
-#define GG_USERLIST_GET 0x02
- * \ingroup importexport
- GG_USERLIST_PUT, /**< Eksport listy kontaktów. */
- GG_USERLIST_GET, /**< Import listy kontaktów. */
-struct gg_userlist_request {
-#define GG_USERLIST_REPLY 0x0010
-#define GG_USERLIST_PUT_REPLY 0x00
-#define GG_USERLIST_PUT_MORE_REPLY 0x02
-#define GG_USERLIST_GET_REPLY 0x06
-#define GG_USERLIST_GET_MORE_REPLY 0x04
- * \ingroup importexport
- GG_USERLIST_PUT_REPLY, /**< Wyeksportowano listy kontaktów. */
- GG_USERLIST_GET_REPLY, /**< Zaimportowano listę kontaktów. */
-struct gg_userlist_reply {
-#define GG_USERLIST100_PUT 0x00
-#define GG_USERLIST100_GET 0x02
- * \ingroup importexport
- * Rodzaj zapytania (10.0).
- GG_USERLIST100_PUT, /**< Eksport listy kontaktów. */
- GG_USERLIST100_GET, /**< Import listy kontaktów. */
-#define GG_USERLIST100_FORMAT_TYPE_NONE 0x00
-#define GG_USERLIST100_FORMAT_TYPE_GG70 0x01
-#define GG_USERLIST100_FORMAT_TYPE_GG100 0x02
- * \ingroup importexport
- * Typ formatu listy kontaktów (10.0).
- GG_USERLIST100_FORMAT_TYPE_NONE, /**< Brak treści listy kontaktów. */
- GG_USERLIST100_FORMAT_TYPE_GG70, /**< Format listy kontaktów zgodny z Gadu-Gadu 7.0. */
- GG_USERLIST100_FORMAT_TYPE_GG100, /**< Format listy kontaktów zgodny z Gadu-Gadu 10.0. */
-#define GG_USERLIST100_REPLY_LIST 0x00
-#define GG_USERLIST100_REPLY_UPTODATE 0x01
-#define GG_USERLIST100_REPLY_ACK 0x10
-#define GG_USERLIST100_REPLY_REJECT 0x12
- * \ingroup importexport
- * Typ odpowiedzi listy kontaktów (10.0).
- GG_USERLIST100_REPLY_LIST, /**< W odpowiedzi znajduje się aktualna lista kontaktów na serwerze. */
- GG_USERLIST100_REPLY_UPTODATE, /**< Komunikat o tym, że lista kontaktów jest już zsynchronizowana. */
- GG_USERLIST100_REPLY_ACK, /**< Potwierdzenie odebrania nowej wersji listy kontaktów. W polu \c gg_userlist100_reply.version znajduje się numer nowej wersji listy kontaktów. */
- GG_USERLIST100_REPLY_REJECT, /**< Odmowa przyjęcia nowej wersji listy kontaktów. W polu \c gg_userlist100_reply.version znajduje się numer wersji listy kontaktów aktualnie przechowywanej przez serwer. */
-struct gg_dcc_tiny_packet {
- uint8_t type; /* rodzaj pakietu */
-struct gg_dcc_small_packet {
- uint32_t type; /* rodzaj pakietu */
-struct gg_dcc_big_packet {
- uint32_t type; /* rodzaj pakietu */
- uint32_t dunno1; /* niewiadoma */
- uint32_t dunno2; /* niewiadoma */
- * póki co, nie znamy dokładnie protokołu. nie wiemy, co czemu odpowiada.
- * nazwy są niepoważne i tymczasowe.
-#define GG_DCC_WANT_FILE 0x0003 /* peer chce plik */
-#define GG_DCC_HAVE_FILE 0x0001 /* więc mu damy */
-#define GG_DCC_HAVE_FILEINFO 0x0003 /* niech ma informacje o pliku */
-#define GG_DCC_GIMME_FILE 0x0006 /* peer jest pewny */
-#define GG_DCC_CATCH_FILE 0x0002 /* wysyłamy plik */
-#define GG_DCC_FILEATTR_READONLY 0x0020
-#define GG_DCC_TIMEOUT_SEND 1800 /* 30 minut */
-#define GG_DCC_TIMEOUT_GET 1800 /* 30 minut */
-#define GG_DCC_TIMEOUT_FILE_ACK 300 /* 5 minut */
-#define GG_DCC_TIMEOUT_VOICE_ACK 300 /* 5 minut */
-#define GG_DCC7_INFO 0x1f
- uint32_t uin; /* numer nadawcy */
- uint32_t type; /* sposób połączenia */
- gg_dcc7_id_t id; /* identyfikator połączenia */
- char info[GG_DCC7_INFO_LEN]; /* informacje o połączeniu "ip port" */
- char hash[GG_DCC7_INFO_HASH_LEN];/* skrót "ip" */
-#define GG_DCC7_NEW 0x20
- gg_dcc7_id_t id; /* identyfikator połączenia */
- uint32_t uin_from; /* numer nadawcy */
- uint32_t uin_to; /* numer odbiorcy */
- uint32_t type; /* rodzaj transmisji */
- unsigned char filename[GG_DCC7_FILENAME_LEN]; /* nazwa pliku */
- uint32_t size; /* rozmiar pliku */
- uint32_t size_hi; /* rozmiar pliku (starsze bajty) */
- unsigned char hash[GG_DCC7_HASH_LEN]; /* hash SHA1 */
-#define GG_DCC7_ACCEPT 0x21
- uint32_t uin; /* numer przyjmującego połączenie */
- gg_dcc7_id_t id; /* identyfikator połączenia */
- uint32_t offset; /* offset przy wznawianiu transmisji */
- uint32_t dunno1; /* 0x00000000 */
-#define GG_DCC7_TYPE_P2P 0x00000001 /**< Połączenie bezpośrednie */
-#define GG_DCC7_TYPE_SERVER 0x00000002 /**< Połączenie przez serwer */
-#define GG_DCC7_REJECT 0x22
- uint32_t uin; /**< Numer odrzucającego połączenie */
- gg_dcc7_id_t id; /**< Identyfikator połączenia */
- uint32_t reason; /**< Powód rozłączenia */
-#define GG_DCC7_REJECT_BUSY 0x00000001 /**< Połączenie bezpośrednie już trwa, nie umiem obsłużyć więcej */
-#define GG_DCC7_REJECT_USER 0x00000002 /**< Użytkownik odrzucił połączenie */
-#define GG_DCC7_REJECT_VERSION 0x00000006 /**< Druga strona ma wersję klienta nieobsługującą połączeń bezpośrednich tego typu */
-#define GG_DCC7_ID_REQUEST 0x23
-struct gg_dcc7_id_request {
- uint32_t type; /**< Rodzaj tranmisji */
-#define GG_DCC7_TYPE_VOICE 0x00000001 /**< Transmisja głosu */
-#define GG_DCC7_TYPE_FILE 0x00000004 /**< transmisja pliku */
-#define GG_DCC7_ID_REPLY 0x23
-struct gg_dcc7_id_reply {
- uint32_t type; /** Rodzaj transmisji */
- gg_dcc7_id_t id; /** Przyznany identyfikator */
-#define GG_DCC7_DUNNO1 0x24
-#define GG_DCC7_TIMEOUT_CONNECT 10 /* 10 sekund */
-#define GG_DCC7_TIMEOUT_SEND 1800 /* 30 minut */
-#define GG_DCC7_TIMEOUT_GET 1800 /* 30 minut */
-#define GG_DCC7_TIMEOUT_FILE_ACK 300 /* 5 minut */
-#define GG_DCC7_TIMEOUT_VOICE_ACK 300 /* 5 minut */
-#define GG_CHAT_INFO_UPDATE_ENTERED 0x01
-#define GG_CHAT_INFO_UPDATE_EXITED 0x03
-#endif /* LIBGADU_LIBGADU_H */
- * c-indentation-style: k&r
- * indent-tabs-mode: notnil
--- a/libpurple/protocols/gg/lib/message.c Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1016 +0,0 @@
- * (C) Copyright 2001-2010 Wojtek Kaniewski <wojtekka@irc.pl>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
- * \brief Obsługa wiadomości
- * Plik zawiera funkcje dotyczące obsługi "klasy" gg_message_t, które
- * w przyszłości zostaną dołączone do API. Obecnie używane są funkcje
- * konwersji między tekstem z atrybutami i HTML.
-gg_message_t *gg_message_new(void)
- gm = malloc(sizeof(gg_message_t));
- memset(gm, 0, sizeof(gg_message_t));
- gm->msgclass = GG_CLASS_CHAT;
- gm->seq = (uint32_t) -1;
-int gg_message_init(gg_message_t *gm, int msgclass, int seq, uin_t *recipients,
- size_t recipient_count, char *text, char *html, char *attributes,
- size_t attributes_length, int auto_convert)
- GG_MESSAGE_CHECK(gm, -1);
- memset(gm, 0, sizeof(gg_message_t));
- gm->recipients = recipients;
- gm->recipient_count = recipient_count;
- gm->attributes = attributes;
- gm->attributes_length = attributes_length;
- gm->msgclass = msgclass;
- gm->auto_convert = auto_convert;
-void gg_message_free(gg_message_t *gm)
- free(gm->text_converted);
- free(gm->html_converted);
-int gg_message_set_auto_convert(gg_message_t *gm, int auto_convert)
- GG_MESSAGE_CHECK(gm, -1);
- gm->auto_convert = !!auto_convert;
- if (!gm->auto_convert) {
- free(gm->text_converted);
- free(gm->html_converted);
- gm->text_converted = NULL;
- gm->html_converted = NULL;
-int gg_message_get_auto_convert(gg_message_t *gm)
- GG_MESSAGE_CHECK(gm, -1);
- return gm->auto_convert;
-int gg_message_set_recipients(gg_message_t *gm, const uin_t *recipients, size_t recipient_count)
- GG_MESSAGE_CHECK(gm, -1);
- if (recipient_count >= INT_MAX / sizeof(uin_t)) {
- if ((recipients == NULL) || (recipient_count == 0)) {
- gm->recipient_count = 0;
- tmp = realloc(gm->recipients, recipient_count * sizeof(uin_t));
- memcpy(tmp, recipients, recipient_count * sizeof(uin_t));
- gm->recipient_count = recipient_count;
-int gg_message_set_recipient(gg_message_t *gm, uin_t recipient)
- return gg_message_set_recipients(gm, &recipient, 1);
-int gg_message_get_recipients(gg_message_t *gm, const uin_t **recipients, size_t *recipient_count)
- GG_MESSAGE_CHECK(gm, -1);
- if (recipients != NULL)
- *recipients = gm->recipients;
- if (recipient_count != NULL)
- *recipient_count = gm->recipient_count;
-uin_t gg_message_get_recipient(gg_message_t *gm)
- GG_MESSAGE_CHECK(gm, (uin_t) -1);
- if ((gm->recipients == NULL) || (gm->recipient_count < 1)) {
- return gm->recipients[0];
-int gg_message_set_class(gg_message_t *gm, uint32_t msgclass)
- GG_MESSAGE_CHECK(gm, -1);
- gm->msgclass = msgclass;
-uint32_t gg_message_get_class(gg_message_t *gm)
- GG_MESSAGE_CHECK(gm, (uint32_t) -1);
-int gg_message_set_seq(gg_message_t *gm, uint32_t seq)
- GG_MESSAGE_CHECK(gm, -1);
-uint32_t gg_message_get_seq(gg_message_t *gm)
- GG_MESSAGE_CHECK(gm, (uint32_t) -1);
-int gg_message_set_text(gg_message_t *gm, const char *text)
- GG_MESSAGE_CHECK(gm, -1);
- free(gm->html_converted);
- gm->html_converted = NULL;
-const char *gg_message_get_text(gg_message_t *gm)
- GG_MESSAGE_CHECK(gm, NULL);
- if (gm->text_converted != NULL)
- return gm->text_converted;
- if (gm->text == NULL && gm->html != NULL && gm->auto_convert) {
- free(gm->text_converted);
- len = gg_message_html_to_text(NULL, gm->html);
- gm->text_converted = malloc(len + 1);
- if (gm->text_converted == NULL)
- gg_message_html_to_text(gm->text_converted, gm->html);
- return gm->text_converted;
-int gg_message_set_html(gg_message_t *gm, const char *html)
- GG_MESSAGE_CHECK(gm, -1);
- free(gm->text_converted);
- gm->text_converted = NULL;
-const char *gg_message_get_html(gg_message_t *gm)
- GG_MESSAGE_CHECK(gm, NULL);
- if (gm->html_converted != NULL)
- return gm->html_converted;
- if (gm->html == NULL && gm->text != NULL && gm->auto_convert) {
- free(gm->html_converted);
- len = gg_message_text_to_html(NULL, gm->text, GG_ENCODING_UTF8, gm->attributes, gm->attributes_length);
- gm->html_converted = malloc(len + 1);
- if (gm->html_converted == NULL)
- gg_message_text_to_html(gm->html_converted, gm->text,
- GG_ENCODING_UTF8, gm->attributes, gm->attributes_length);
- return gm->html_converted;
-int gg_message_set_attributes(gg_message_t *gm, const char *attributes, size_t length)
- GG_MESSAGE_CHECK(gm, -1);
- if ((attributes == NULL) || (length == 0)) {
- gm->attributes_length = 0;
- tmp = realloc(gm->attributes, length);
- gm->attributes_length = length;
- free(gm->html_converted);
- gm->html_converted = NULL;
-int gg_message_get_attributes(gg_message_t *gm, const char **attributes, size_t *attributes_length)
- GG_MESSAGE_CHECK(gm, -1);
- if (attributes != NULL)
- *attributes = gm->attributes;
- if (attributes_length != NULL)
- *attributes_length = gm->attributes_length;
- * \internal Dodaje tekst na koniec bufora.
- * \param dst Wskaźnik na bufor roboczy
- * \param pos Wskaźnik na aktualne położenie w buforze roboczym
- * \param src Dodawany tekst
- * \param len Długość dodawanego tekstu
-static void gg_append(char *dst, size_t *pos, const void *src, size_t len)
- memcpy(&dst[*pos], src, len);
- * \internal Zamienia tekst z formatowaniem Gadu-Gadu na HTML.
- * \param dst Bufor wynikowy (może być \c NULL)
- * \param src Tekst źródłowy
- * \param encoding Kodowanie tekstu źródłowego oraz wynikowego
- * \param format Atrybuty tekstu źródłowego
- * \param format_len Długość bloku atrybutów tekstu źródłowego
- * \note Wynikowy tekst nie jest idealnym kodem HTML, ponieważ ma jak
- * dokładniej odzwierciedlać to, co wygenerowałby oryginalny klient.
- * \note Dokleja \c \\0 na końcu bufora wynikowego.
- * \return Długość tekstu wynikowego bez \c \\0 (nawet jeśli \c dst to \c NULL).
-size_t gg_message_text_to_html(char *dst, const char *src,
- gg_encoding_t encoding, const unsigned char *format, size_t format_len)
- const char span_fmt[] = "<span style=\"color:#%02x%02x%02x; font-family:'MS Shell Dlg 2'; font-size:9pt; \">";
- const size_t span_len = 75;
- const char img_fmt[] = "<img name=\"%02x%02x%02x%02x%02x%02x%02x%02x\">";
- const size_t img_len = 29;
- unsigned char old_attr = 0;
- const unsigned char default_color[] = {'\x00', '\x00', '\x00'};
- const unsigned char *old_color = NULL;
- /* Pętla przechodzi też przez kończące \0, żeby móc dokleić obrazek
- /* Sprawdź, czy bajt jest kontynuacją znaku UTF-8. */
- if (encoding == GG_ENCODING_UTF8 && (src[i] & 0xc0) == 0x80)
- /* GG_FONT_IMAGE powinno dotyczyć tylko jednego znaku, więc czyścimy stary atrybut */
- if (!in_char && (old_attr & GG_FONT_IMAGE) != 0)
- old_attr &= ~GG_FONT_IMAGE;
- /* Analizuj wszystkie atrybuty dotyczące aktualnego znaku. */
- /* Nie wstawiamy niczego wewnątrz wielobajtowego znaku UTF-8. */
- if (format_idx + 3 > format_len)
- /* (format_idx + 3 <= format_len) && (format_idx > 0)
- assert(format != NULL);
- attr_pos = format[format_idx] | (format[format_idx + 1] << 8);
- attr = format[format_idx + 2];
- /* Nie doklejaj atrybutów na końcu, co najwyżej obrazki. */
- attr &= ~(GG_FONT_BOLD | GG_FONT_ITALIC | GG_FONT_UNDERLINE | GG_FONT_COLOR);
- if (attr_pos != char_pos) {
- if ((attr & GG_FONT_COLOR) != 0)
- if ((attr & GG_FONT_IMAGE) != 0)
- if ((old_attr & GG_FONT_UNDERLINE) != 0)
- gg_append(dst, &len, "</u>", 4);
- if ((old_attr & GG_FONT_ITALIC) != 0)
- gg_append(dst, &len, "</i>", 4);
- if ((old_attr & GG_FONT_BOLD) != 0)
- gg_append(dst, &len, "</b>", 4);
- if ((attr & (GG_FONT_BOLD | GG_FONT_ITALIC | GG_FONT_UNDERLINE | GG_FONT_COLOR)) != 0) {
- const unsigned char *color;
- if (((attr & GG_FONT_COLOR) != 0) && (format_idx + 3 <= format_len)) {
- color = &format[format_idx];
- if (old_color == NULL || memcmp(color, old_color, 3) != 0) {
- gg_append(dst, &len, "</span>", 7);
- sprintf(&dst[len], span_fmt, color[0], color[1], color[2]);
- if ((attr & GG_FONT_BOLD) != 0)
- gg_append(dst, &len, "<b>", 3);
- if ((attr & GG_FONT_ITALIC) != 0)
- gg_append(dst, &len, "<i>", 3);
- if ((attr & GG_FONT_UNDERLINE) != 0)
- gg_append(dst, &len, "<u>", 3);
- if (((attr & GG_FONT_IMAGE) != 0) && (format_idx + 10 <= format_len)) {
- sprintf(&dst[len], img_fmt,
- format[format_idx + 9],
- format[format_idx + 8],
- format[format_idx + 7],
- format[format_idx + 6],
- format[format_idx + 5],
- format[format_idx + 4],
- format[format_idx + 3],
- format[format_idx + 2]);
- /* Znaki oznaczone jako GG_FONT_IMAGE nie są częścią wiadomości. */
- if ((old_attr & GG_FONT_IMAGE) != 0) {
- /* Jesteśmy na początku tekstu i choć nie było atrybutów dla pierwszego
- * znaku, ponieważ tekst nie jest pusty, trzeba otworzyć <span>. */
- sprintf(&dst[len], span_fmt, default_color[0], default_color[1], default_color[2]);
- old_color = default_color;
- /* Doklej znak zachowując htmlowe escapowanie. */
- gg_append(dst, &len, "&", 5);
- gg_append(dst, &len, "<", 4);
- gg_append(dst, &len, ">", 4);
- gg_append(dst, &len, "'", 6);
- gg_append(dst, &len, """, 6);
- gg_append(dst, &len, "<br>", 4);
- if ((old_attr & GG_FONT_UNDERLINE) != 0)
- gg_append(dst, &len, "</u>", 4);
- if ((old_attr & GG_FONT_ITALIC) != 0)
- gg_append(dst, &len, "</i>", 4);
- if ((old_attr & GG_FONT_BOLD) != 0)
- gg_append(dst, &len, "</b>", 4);
- gg_append(dst, &len, "</span>", 7);
- * \internal Dokleja nowe atrybuty formatowania, jeśli konieczne, oraz inkrementuje pozycję znaku w tekście.
- * \param pos Wskaźnik na zmienną przechowującą pozycję znaku w tekście
- * \param attr_flag Aktualna flaga atrybutu formatowania
- * \param old_attr_flag Wskaźnik na poprzednią flagę atrybutu formatowania
- * \param color Wskaźnik na tablicę z aktualnym kolorem RGB (jeśli \p attr_flag
- * nie zawiera flagi \c GG_FONT_COLOR, ignorowane)
- * \param old_color Wskaźnik na tablicę z poprzednim kolorem RGB
- * \param imgs_size Rozmiar atrybutów formatowania obrazków znajdujących się
- * obecnie w tablicy atrybutów formatowania, w bajtach
- * \param format Wskaźnik na wskaźnik do tablicy atrybutów formatowania
- * \param format_len Wskaźnik na zmienną zawierającą długość tablicy atrybutów
- * formatowania, w bajtach (może być \c NULL)
-static void gg_after_append_formatted_char(uint16_t *pos,
- unsigned char attr_flag, unsigned char *old_attr_flag,
- const unsigned char *color, unsigned char *old_color, size_t imgs_size,
- unsigned char **format, size_t *format_len)
- const size_t color_size = 3;
- if ((attr_flag & GG_FONT_COLOR) != 0)
- if (*old_attr_flag != attr_flag || (has_color && memcmp(old_color, color, color_size) != 0)) {
- size_t attr_size = sizeof(*pos) + sizeof(attr_flag) + (has_color ? color_size : 0);
- /* Staramy się naśladować oryginalnego klienta i atrybuty obrazków trzymamy na końcu */
- memmove(*format + attr_size, *format, imgs_size);
- **format = (unsigned char) (*pos & (uint16_t) 0x00ffU);
- **format = (unsigned char) ((*pos & (uint16_t) 0xff00U) >> 8);
- memcpy(*format, color, color_size);
- if (format_len != NULL)
- *format_len += attr_size;
- *old_attr_flag = attr_flag;
- memcpy(old_color, color, color_size);
- * \internal Zamienia tekst w formacie HTML na czysty tekst.
- * \param dst Bufor wynikowy (może być \c NULL)
- * \param format Bufor wynikowy z atrybutami formatowania (może być \c NULL)
- * \param format_len Wskaźnik na zmienną, do której zostanie zapisana potrzebna
- * wielkość bufora wynikowego z atrybutami formatowania,
- * w bajtach (może być \c NULL)
- * \param html Tekst źródłowy
- * \param encoding Kodowanie tekstu źródłowego oraz wynikowego
- * \note Dokleja \c \\0 na końcu bufora wynikowego.
- * \return Długość bufora wynikowego bez \c \\0 (nawet jeśli \c dst to \c NULL).
-size_t gg_message_html_to_text(char *dst, unsigned char *format,
- size_t *format_len, const char *html, gg_encoding_t encoding)
- const char *src, *entity = NULL, *tag = NULL;
- int in_tag = 0, in_entity = 0, in_bold = 0, in_italic = 0, in_underline = 0;
- unsigned char color[3] = { 0 }, old_color[3] = { 0 };
- unsigned char attr_flag = 0, old_attr_flag = 0;
- size_t len = 0, imgs_size = 0;
- if (format_len != NULL)
- for (src = html; *src != 0; src++) {
- if (in_entity && !(isalnum(*src) || *src == '#' || *src == ';')) {
- size_t i, append_len = src - entity;
- gg_append(dst, &len, entity, append_len);
- for (i = 0; i < append_len; i++) {
- if (encoding != GG_ENCODING_UTF8 || (entity[i] & 0xc0) != 0x80) {
- gg_after_append_formatted_char(&pos, attr_flag,
- &old_attr_flag, color, old_color, imgs_size,
- if (in_tag && (*src == '>')) {
- if (strncmp(tag, "<br", 3) == 0) {
- gg_after_append_formatted_char(&pos, attr_flag,
- &old_attr_flag, color, old_color,
- imgs_size, &format, format_len);
- } else if (strncmp(tag, "<img name=\"", 11) == 0 || strncmp(tag, "<img name=\'", 11) == 0) {
- /* 17 bo jeszcze cudzysłów musi być zamknięty */
- for (i = 0; i < 16; i++) {
- if (!isxdigit(tag[i])) {
- unsigned char img_attr[13];
- img_attr[0] = (unsigned char) (pos & (uint16_t) 0x00ffU);
- img_attr[1] = (unsigned char) ((pos & (uint16_t) 0xff00U) >> 8);
- img_attr[2] = GG_FONT_IMAGE;
- for (i = 0; i < 16; i += 2) {
- (unsigned char)strtoul(buf, NULL, 16);
- memcpy(format, img_attr, sizeof(img_attr));
- format += sizeof(img_attr);
- if (format_len != NULL)
- *format_len += sizeof(img_attr);
- imgs_size += sizeof(img_attr);
- if (encoding == GG_ENCODING_UTF8)
- /* Nie używamy tutaj gg_after_append_formatted_char().
- * Po pierwsze to praktycznie niczego by nie
- * zmieniło, a po drugie nie wszystkim klientom
- * mogłaby się spodobać redefinicja atrybutów
- * formatowania dla jednego znaku (bo np. najpierw
- * byśmy zdefiniowali bolda od znaku 10, a potem
- * by się okazało, że znak 10 to obrazek).
- /* Resetujemy atrybuty, aby je w razie czego
- * redefiniować od następnego znaku, co by sobie
- * nikt przypadkiem nie pomyślał, że GG_FONT_IMAGE
- * dotyczy więcej, niż jednego znaku.
- * Tak samo robi oryginalny klient.
- } else if (strncmp(tag, "<b>", 3) == 0) {
- attr_flag |= GG_FONT_BOLD;
- } else if (strncmp(tag, "</b>", 4) == 0) {
- attr_flag &= ~GG_FONT_BOLD;
- } else if (strncmp(tag, "<i>", 3) == 0) {
- attr_flag |= GG_FONT_ITALIC;
- } else if (strncmp(tag, "</i>", 4) == 0) {
- attr_flag &= ~GG_FONT_ITALIC;
- } else if (strncmp(tag, "<u>", 3) == 0) {
- attr_flag |= GG_FONT_UNDERLINE;
- } else if (strncmp(tag, "</u>", 4) == 0) {
- if (in_underline > 0) {
- attr_flag &= ~GG_FONT_UNDERLINE;
- } else if (strncmp(tag, "<span ", 6) == 0) {
- for (tag += 6; tag < src - 8; tag++) {
- if (*tag == '\"' || *tag == '\'' || *tag == ' ') {
- if (strncmp(tag + 1, "color:#", 7) == 0) {
- for (i = 0; i < 6; i++) {
- if (!isxdigit(tag[i])) {
- for (i = 0; i < 6; i += 2) {
- color[i / 2] = (unsigned char) strtoul(buf, NULL, 16);
- attr_flag |= GG_FONT_COLOR;
- } else if (strncmp(tag, "</span", 6) == 0) {
- /* Można by trzymać kolory na stosie i tutaj
- * przywracać poprzedni, ale to raczej zbędne */
- attr_flag &= ~GG_FONT_COLOR;
- if (in_entity && *src == ';') {
- if (strncmp(entity, "<", 4) == 0)
- else if (strncmp(entity, ">", 4) == 0)
- else if (strncmp(entity, """, 6) == 0)
- else if (strncmp(entity, "'", 6) == 0)
- else if (strncmp(entity, "&", 5) == 0)
- else if (strncmp(entity, " ", 6) == 0) {
- if (encoding == GG_ENCODING_UTF8)
- if (strncmp(entity, " ", 6) == 0)
- gg_after_append_formatted_char(&pos, attr_flag,
- &old_attr_flag, color, old_color, imgs_size,
- if (in_entity && !(isalnum(*src) || *src == '#'))
- if (encoding != GG_ENCODING_UTF8 || (*src & 0xc0) != 0x80) {
- gg_after_append_formatted_char(&pos, attr_flag,
- &old_attr_flag, color, old_color, imgs_size,
-static size_t gg_message_html_to_text_110_buff(char *dst, const char *html)
- return gg_message_html_to_text(dst, NULL, NULL, html, GG_ENCODING_UTF8);
-static size_t gg_message_text_to_html_110_buff(char *dst, const char *text,
- text_len = strlen(text);
- gg_append(dst, &dst_len, "<span>", 6);
- for (i = 0; i < (size_t)text_len; i++) {
- gg_append(dst, &dst_len, "<", 4);
- gg_append(dst, &dst_len, ">", 4);
- gg_append(dst, &dst_len, "&", 5);
- gg_append(dst, &dst_len, """, 6);
- gg_append(dst, &dst_len, "'", 6);
- gg_append(dst, &dst_len, "<br>", 4);
- else if (c == '\xc2' && text[i + 1] == '\xa0') {
- gg_append(dst, &dst_len, " ", 6);
- gg_append(dst, &dst_len, "</span>", 7);
-char *gg_message_html_to_text_110(const char *html)
- dst_len = gg_message_html_to_text_110_buff(NULL, html) + 1;
- gg_message_html_to_text_110_buff(dst, html);
-char *gg_message_text_to_html_110(const char *text, ssize_t text_len)
- dst_len = gg_message_text_to_html_110_buff(NULL, text, text_len) + 1;
- gg_message_text_to_html_110_buff(dst, text, text_len);
--- a/libpurple/protocols/gg/lib/message.h Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
- * (C) Copyright 2009 Wojtek Kaniewski <wojtekka@irc.pl>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-#ifndef LIBGADU_MESSAGE_H
-#define LIBGADU_MESSAGE_H
- size_t recipient_count;
- size_t attributes_length;
-#define GG_MESSAGE_CHECK(gm, result) \
-int gg_message_init(gg_message_t *gm, int msgclass, int seq, uin_t *recipients,
- size_t recipient_count, char *text, char *xhtml, char *attributes,
- size_t attributes_length, int auto_convert);
-size_t gg_message_html_to_text(char *dst, unsigned char *format,
- size_t *format_len, const char *html, gg_encoding_t encoding);
-size_t gg_message_text_to_html(char *dst, const char *src,
- gg_encoding_t encoding, const unsigned char *format, size_t format_len);
-char * gg_message_html_to_text_110(const char *html);
-char * gg_message_text_to_html_110(const char *text, ssize_t text_len);
-#endif /* LIBGADU_MESSAGE_H */
--- a/libpurple/protocols/gg/lib/network.c Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,310 +0,0 @@
- * (C) Copyright 2011 Wojtek Kaniewski <wojtekka@irc.pl>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-/* Code losely based on sockerpair implementation by Nathan C. Meyrs.
- * The original copyright notice follows: */
- * Copyright 2007, 2010 by Nathan C. Myers <ncm@cantrip.org>
- * This code is Free Software. It may be copied freely, in original or
- * modified form, subject only to the restrictions that (1) the author is
- * relieved from all responsibilities for any use for any purpose, and (2)
- * this copyright notice must be retained, unchanged, in its entirety. If
- * for any reason the author might be held responsible for any consequences
- * of copying or use, license is withheld.
-int gg_win32_socketpair(int sv[2])
- struct sockaddr_in sin;
- socklen_t sin_len = sizeof(sin);
- server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- if (setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp)) == -1)
- if (bind(server, (struct sockaddr*) &sin, sin_len) == -1)
- if (listen(server, 1) == -1)
- if (getsockname(server, (struct sockaddr*) &sin, &sin_len) == -1)
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- sv[0] = socket(AF_INET, SOCK_STREAM, 0);
- if (connect(sv[0], (struct sockaddr*) &sin, sin_len) == -1)
- sv[1] = accept(server, NULL, NULL);
-static int gg_win32_map_wsa_error_to_errno(int wsaewouldblock_map)
- wsa_error = WSAGetLastError();
- /* Tutaj powinny być tłumaczone wszystkie typy błędów sprawdzane przez
- * kod libgadu. Dla spójność są również tłumaczone typy błędów ustawiane
- * Ponadto gdyby okazało się, że jakaś aplikacja na Win32 chce móc
- * polegać jeszcze na innych wartościach errno, można tutaj dodać
- * ich tłumaczenie. Najpierw jednak zawsze trzeba porównać dokumentacje,
- * aby upewnić się co do poprawności tłumaczenia (patrz WSAEWOULDBLOCK,
- * które można tłumaczyć na EWOULDBLOCK lub EAGAIN, a nawet na
- * EINPROGRESS w przypadku connect()).
- /* Typy błędów sprawdzane przez libgadu. */
- return wsaewouldblock_map;
- /* Typy błędów ustawiane przez libgadu. */
- /* Najlepiej zwrócić oryginalny kod błędu. I tak będzie co najwyżej
- * wyświetlony w komunikacie debugowym, a tym sposobem będzie łatwiej
- * dojść przyczyny problemu. */
-int gg_win32_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
- res = accept(sockfd, addr, addrlen);
- errno = gg_win32_map_wsa_error_to_errno(EAGAIN);
-int gg_win32_bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
- res = bind(sockfd, addr, addrlen);
- errno = gg_win32_map_wsa_error_to_errno(EAGAIN);
-int gg_win32_close(int sockfd)
- res = closesocket(sockfd);
- errno = gg_win32_map_wsa_error_to_errno(EAGAIN);
-int gg_win32_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
- res = connect(sockfd, addr, addrlen);
- errno = gg_win32_map_wsa_error_to_errno(EINPROGRESS);
-struct hostent *gg_win32_gethostbyname(const char *name)
- res = gethostbyname(name);
- errno = gg_win32_map_wsa_error_to_errno(EAGAIN);
-int gg_win32_getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
- res = getsockname(sockfd, addr, addrlen);
- errno = gg_win32_map_wsa_error_to_errno(EAGAIN);
-int gg_win32_getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen)
- res = getsockopt(sockfd, level, optname, optval, optlen);
- errno = gg_win32_map_wsa_error_to_errno(EAGAIN);
-int gg_win32_ioctl(int d, int request, int *argp)
- res = ioctlsocket(d, request, (u_long *)argp);
- errno = gg_win32_map_wsa_error_to_errno(EAGAIN);
-int gg_win32_listen(int sockfd, int backlog)
- res = listen(sockfd, backlog);
- errno = gg_win32_map_wsa_error_to_errno(EAGAIN);
-int gg_win32_recv(int sockfd, void *buf, size_t len, int flags)
- res = recv(sockfd, buf, len, flags);
- errno = gg_win32_map_wsa_error_to_errno(EAGAIN);
-int gg_win32_send(int sockfd, const void *buf, size_t len, int flags)
- res = send(sockfd, buf, len, flags);
- errno = gg_win32_map_wsa_error_to_errno(EAGAIN);
-int gg_win32_setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen)
- res = setsockopt(sockfd, level, optname, optval, optlen);
- errno = gg_win32_map_wsa_error_to_errno(EAGAIN);
-int gg_win32_socket(int domain, int type, int protocol)
- res = socket(domain, type, protocol);
- errno = gg_win32_map_wsa_error_to_errno(EAGAIN);
--- a/libpurple/protocols/gg/lib/network.h Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
- * (C) Copyright 2001-2002 Wojtek Kaniewski <wojtekka@irc.pl>
- * Robert J. Woźny <speedy@ziew.org>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
- * \brief Makra zapewniające kompatybilność API do obsługi sieci na różnych systemach
-#ifndef LIBGADU_NETWORK_H
-#define LIBGADU_NETWORK_H
-/* Obecnie na Win32 tylko MSVC definiuje te typy błędów. Na wypadek, gdyby
- * jednak Cygwin bądź MinGW zaczęły je definiować, używamy bardziej ogólnych
-# define ECONNRESET WSAECONNRESET
-# define EINPROGRESS WSAEINPROGRESS
-# define ENOTCONN WSAENOTCONN
-# define ETIMEDOUT WSAETIMEDOUT
-# define accept gg_win32_accept
-# define bind gg_win32_bind
-# define close gg_win32_close
-# define connect gg_win32_connect
-# define gethostbyname gg_win32_gethostbyname
-# define getsockname gg_win32_getsockname
-# define getsockopt gg_win32_getsockopt
-# define ioctl gg_win32_ioctl
-# define listen gg_win32_listen
-# define recv gg_win32_recv
-# define send gg_win32_send
-# define setsockopt gg_win32_setsockopt
-# define socket gg_win32_socket
-# define socketpair(a, b, c, d) gg_win32_socketpair(d)
-int gg_win32_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
-int gg_win32_bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
-int gg_win32_close(int sockfd);
-int gg_win32_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
-struct hostent *gg_win32_gethostbyname(const char *name);
-int gg_win32_getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
-int gg_win32_getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);
-int gg_win32_ioctl(int d, int request, int *argp);
-int gg_win32_listen(int sockfd, int backlog);
-int gg_win32_recv(int sockfd, void *buf, size_t len, int flags);
-int gg_win32_send(int sockfd, const void *buf, size_t len, int flags);
-int gg_win32_setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
-int gg_win32_socket(int domain, int type, int protocol);
-int gg_win32_socketpair(int sv[2]);
-static inline void gg_win32_init_network(void)
- if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
-# include <sys/socket.h>
-# include <netinet/in.h>
-# define INADDR_NONE ((in_addr_t) 0xffffffff)
-# define AF_LOCAL AF_UNIX
-static inline int gg_fd_set_nonblocking(int fd)
- success = (ioctl(fd, FIONBIO, &one) == 0);
- success = (fcntl(fd, F_SETFL, O_NONBLOCK) == 0);
-#endif /* LIBGADU_NETWORK_H */
--- a/libpurple/protocols/gg/lib/obsolete.c Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,250 +0,0 @@
- * (C) Copyright 2001-2003 Wojtek Kaniewski <wojtekka@irc.pl>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
- * \brief Nieaktualne funkcje
- * Plik zawiera definicje funkcji, które są już nieaktualne ze względu
- * na zmiany w protokole. Programy konsolidowane ze starszych wersjami
- * bibliotek powinny nadal mieć możliwość działania, mimo ograniczonej
-struct gg_http *gg_userlist_get(uin_t uin, const char *passwd, int async)
- gg_debug(GG_DEBUG_MISC, "// gg_userlist_get() is obsolete. use gg_userlist_request() instead!\n");
-int gg_userlist_get_watch_fd(struct gg_http *h)
-void gg_userlist_get_free(struct gg_http *h)
-struct gg_http *gg_userlist_put(uin_t uin, const char *password, const char *contacts, int async)
- gg_debug(GG_DEBUG_MISC, "// gg_userlist_put() is obsolete. use gg_userlist_request() instead!\n");
-int gg_userlist_put_watch_fd(struct gg_http *h)
-void gg_userlist_put_free(struct gg_http *h)
-struct gg_http *gg_userlist_remove(uin_t uin, const char *passwd, int async)
- gg_debug(GG_DEBUG_MISC, "// gg_userlist_remove() is obsolete. use gg_userlist_request() instead!\n");
-int gg_userlist_remove_watch_fd(struct gg_http *h)
-void gg_userlist_remove_free(struct gg_http *h)
-struct gg_http *gg_search(const struct gg_search_request *r, int async)
- gg_debug(GG_DEBUG_MISC, "// gg_search() is obsolete. use gg_search50() instead!\n");
-int gg_search_watch_fd(struct gg_http *h)
-void gg_search_free(struct gg_http *h)
-const struct gg_search_request *gg_search_request_mode_0(char *nickname,
- char *first_name, char *last_name, char *city, int gender,
- int min_birth, int max_birth, int active, int start)
-const struct gg_search_request *gg_search_request_mode_1(char *email, int active, int start)
-const struct gg_search_request *gg_search_request_mode_2(char *phone, int active, int start)
-const struct gg_search_request *gg_search_request_mode_3(uin_t uin, int active, int start)
-void gg_search_request_free(struct gg_search_request *r)
-struct gg_http *gg_register(const char *email, const char *password, int async)
- gg_debug(GG_DEBUG_MISC, "// gg_register() is obsolete. use gg_register3() instead!\n");
-struct gg_http *gg_register2(const char *email, const char *password, const char *qa, int async)
- gg_debug(GG_DEBUG_MISC, "// gg_register2() is obsolete. use gg_register3() instead!\n");
-struct gg_http *gg_unregister(uin_t uin, const char *password, const char *email, int async)
- gg_debug(GG_DEBUG_MISC, "// gg_unregister() is obsolete. use gg_unregister3() instead!\n");
-struct gg_http *gg_unregister2(uin_t uin, const char *password, const char *qa, int async)
- gg_debug(GG_DEBUG_MISC, "// gg_unregister2() is obsolete. use gg_unregister3() instead!\n");
-struct gg_http *gg_change_passwd(uin_t uin, const char *passwd, const char *newpasswd, const char *newemail, int async)
- gg_debug(GG_DEBUG_MISC, "// gg_change_passwd() is obsolete. use gg_change_passwd4() instead!\n");
-struct gg_http *gg_change_passwd2(uin_t uin, const char *passwd,
- const char *newpasswd, const char *email, const char *newemail,
- gg_debug(GG_DEBUG_MISC, "// gg_change_passwd2() is obsolete. use gg_change_passwd4() instead!\n");
-struct gg_http *gg_change_passwd3(uin_t uin, const char *passwd, const char *newpasswd, const char *qa, int async)
- gg_debug(GG_DEBUG_MISC, "// gg_change_passwd3() is obsolete. use gg_change_passwd4() instead!\n");
-struct gg_http *gg_remind_passwd(uin_t uin, int async)
- gg_debug(GG_DEBUG_MISC, "// gg_remind_passwd() is obsolete. use gg_remind_passwd3() instead!\n");
-struct gg_http *gg_remind_passwd2(uin_t uin, const char *tokenid, const char *tokenval, int async)
- gg_debug(GG_DEBUG_MISC, "// gg_remind_passwd2() is obsolete. use gg_remind_passwd3() instead!\n");
-struct gg_http *gg_change_info(uin_t uin, const char *passwd, const struct gg_change_info_request *request, int async)
- gg_debug(GG_DEBUG_MISC, "// gg_change_info() is obsolete. use gg_pubdir50() instead\n");
-struct gg_change_info_request *gg_change_info_request_new(
- const char *first_name, const char *last_name, const char *nickname,
- const char *email, int born, int gender, const char *city)
-void gg_change_info_request_free(struct gg_change_info_request *r)
-int gg_resolve(int *fd, int *pid, const char *hostname)
-void gg_resolve_pthread_cleanup(void *arg, int kill)
-int gg_resolve_pthread(int *fd, void **resolver, const char *hostname)
-int gg_pubdir50_handle_reply(struct gg_event *e, const char *packet, int length)
-void gg_login_hash_sha1(const char *password, uint32_t seed, uint8_t *result)
- if (gg_login_hash_sha1_2(password, seed, result) != 0)
--- a/libpurple/protocols/gg/lib/packets.pb-c.c Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2603 +0,0 @@
-/* Generated by the protocol buffer compiler. DO NOT EDIT! */
-/* Generated from: packets.proto */
-/* Do not generate deprecated warnings for self */
-#ifndef PROTOBUF_C__NO_DEPRECATED
-#define PROTOBUF_C__NO_DEPRECATED
-#include "packets.pb-c.h"
-void gg110_login_ok__init
- (GG110LoginOK *message)
- static GG110LoginOK init_value = GG110_LOGIN_OK__INIT;
-size_t gg110_login_ok__get_packed_size
- (const GG110LoginOK *message)
- assert(message->base.descriptor == &gg110_login_ok__descriptor);
- return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
-size_t gg110_login_ok__pack
- (const GG110LoginOK *message,
- assert(message->base.descriptor == &gg110_login_ok__descriptor);
- return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
-size_t gg110_login_ok__pack_to_buffer
- (const GG110LoginOK *message,
- ProtobufCBuffer *buffer)
- assert(message->base.descriptor == &gg110_login_ok__descriptor);
- return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
- (ProtobufCAllocator *allocator,
- return (GG110LoginOK *)
- protobuf_c_message_unpack (&gg110_login_ok__descriptor,
-void gg110_login_ok__free_unpacked
- (GG110LoginOK *message,
- ProtobufCAllocator *allocator)
- assert(message->base.descriptor == &gg110_login_ok__descriptor);
- protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
- static GG110Pong init_value = GG110_PONG__INIT;
-size_t gg110_pong__get_packed_size
- (const GG110Pong *message)
- assert(message->base.descriptor == &gg110_pong__descriptor);
- return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
- (const GG110Pong *message,
- assert(message->base.descriptor == &gg110_pong__descriptor);
- return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
-size_t gg110_pong__pack_to_buffer
- (const GG110Pong *message,
- ProtobufCBuffer *buffer)
- assert(message->base.descriptor == &gg110_pong__descriptor);
- return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
- (ProtobufCAllocator *allocator,
- protobuf_c_message_unpack (&gg110_pong__descriptor,
-void gg110_pong__free_unpacked
- ProtobufCAllocator *allocator)
- assert(message->base.descriptor == &gg110_pong__descriptor);
- protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
- static GG110Ack init_value = GG110_ACK__INIT;
-size_t gg110_ack__get_packed_size
- (const GG110Ack *message)
- assert(message->base.descriptor == &gg110_ack__descriptor);
- return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
- (const GG110Ack *message,
- assert(message->base.descriptor == &gg110_ack__descriptor);
- return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
-size_t gg110_ack__pack_to_buffer
- (const GG110Ack *message,
- ProtobufCBuffer *buffer)
- assert(message->base.descriptor == &gg110_ack__descriptor);
- return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
- (ProtobufCAllocator *allocator,
- protobuf_c_message_unpack (&gg110_ack__descriptor,
-void gg110_ack__free_unpacked
- ProtobufCAllocator *allocator)
- assert(message->base.descriptor == &gg110_ack__descriptor);
- protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
- static GG105Login init_value = GG105_LOGIN__INIT;
-size_t gg105_login__get_packed_size
- (const GG105Login *message)
- assert(message->base.descriptor == &gg105_login__descriptor);
- return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
-size_t gg105_login__pack
- (const GG105Login *message,
- assert(message->base.descriptor == &gg105_login__descriptor);
- return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
-size_t gg105_login__pack_to_buffer
- (const GG105Login *message,
- ProtobufCBuffer *buffer)
- assert(message->base.descriptor == &gg105_login__descriptor);
- return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
- (ProtobufCAllocator *allocator,
- protobuf_c_message_unpack (&gg105_login__descriptor,
-void gg105_login__free_unpacked
- ProtobufCAllocator *allocator)
- assert(message->base.descriptor == &gg105_login__descriptor);
- protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
-void gg110_message_ack_link__init
- (GG110MessageAckLink *message)
- static GG110MessageAckLink init_value = GG110_MESSAGE_ACK_LINK__INIT;
-size_t gg110_message_ack_link__get_packed_size
- (const GG110MessageAckLink *message)
- assert(message->base.descriptor == &gg110_message_ack_link__descriptor);
- return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
-size_t gg110_message_ack_link__pack
- (const GG110MessageAckLink *message,
- assert(message->base.descriptor == &gg110_message_ack_link__descriptor);
- return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
-size_t gg110_message_ack_link__pack_to_buffer
- (const GG110MessageAckLink *message,
- ProtobufCBuffer *buffer)
- assert(message->base.descriptor == &gg110_message_ack_link__descriptor);
- return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
- gg110_message_ack_link__unpack
- (ProtobufCAllocator *allocator,
- return (GG110MessageAckLink *)
- protobuf_c_message_unpack (&gg110_message_ack_link__descriptor,
-void gg110_message_ack_link__free_unpacked
- (GG110MessageAckLink *message,
- ProtobufCAllocator *allocator)
- assert(message->base.descriptor == &gg110_message_ack_link__descriptor);
- protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
-void gg110_message_ack__init
- (GG110MessageAck *message)
- static GG110MessageAck init_value = GG110_MESSAGE_ACK__INIT;
-size_t gg110_message_ack__get_packed_size
- (const GG110MessageAck *message)
- assert(message->base.descriptor == &gg110_message_ack__descriptor);
- return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
-size_t gg110_message_ack__pack
- (const GG110MessageAck *message,
- assert(message->base.descriptor == &gg110_message_ack__descriptor);
- return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
-size_t gg110_message_ack__pack_to_buffer
- (const GG110MessageAck *message,
- ProtobufCBuffer *buffer)
- assert(message->base.descriptor == &gg110_message_ack__descriptor);
- return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
- gg110_message_ack__unpack
- (ProtobufCAllocator *allocator,
- return (GG110MessageAck *)
- protobuf_c_message_unpack (&gg110_message_ack__descriptor,
-void gg110_message_ack__free_unpacked
- (GG110MessageAck *message,
- ProtobufCAllocator *allocator)
- assert(message->base.descriptor == &gg110_message_ack__descriptor);
- protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
- static GG110Event init_value = GG110_EVENT__INIT;
-size_t gg110_event__get_packed_size
- (const GG110Event *message)
- assert(message->base.descriptor == &gg110_event__descriptor);
- return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
-size_t gg110_event__pack
- (const GG110Event *message,
- assert(message->base.descriptor == &gg110_event__descriptor);
- return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
-size_t gg110_event__pack_to_buffer
- (const GG110Event *message,
- ProtobufCBuffer *buffer)
- assert(message->base.descriptor == &gg110_event__descriptor);
- return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
- (ProtobufCAllocator *allocator,
- protobuf_c_message_unpack (&gg110_event__descriptor,
-void gg110_event__free_unpacked
- ProtobufCAllocator *allocator)
- assert(message->base.descriptor == &gg110_event__descriptor);
- protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
-void gg110_recv_message__init
- (GG110RecvMessage *message)
- static GG110RecvMessage init_value = GG110_RECV_MESSAGE__INIT;
-size_t gg110_recv_message__get_packed_size
- (const GG110RecvMessage *message)
- assert(message->base.descriptor == &gg110_recv_message__descriptor);
- return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
-size_t gg110_recv_message__pack
- (const GG110RecvMessage *message,
- assert(message->base.descriptor == &gg110_recv_message__descriptor);
- return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
-size_t gg110_recv_message__pack_to_buffer
- (const GG110RecvMessage *message,
- ProtobufCBuffer *buffer)
- assert(message->base.descriptor == &gg110_recv_message__descriptor);
- return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
- gg110_recv_message__unpack
- (ProtobufCAllocator *allocator,
- return (GG110RecvMessage *)
- protobuf_c_message_unpack (&gg110_recv_message__descriptor,
-void gg110_recv_message__free_unpacked
- (GG110RecvMessage *message,
- ProtobufCAllocator *allocator)
- assert(message->base.descriptor == &gg110_recv_message__descriptor);
- protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
-void gg110_send_message__init
- (GG110SendMessage *message)
- static GG110SendMessage init_value = GG110_SEND_MESSAGE__INIT;
-size_t gg110_send_message__get_packed_size
- (const GG110SendMessage *message)
- assert(message->base.descriptor == &gg110_send_message__descriptor);
- return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
-size_t gg110_send_message__pack
- (const GG110SendMessage *message,
- assert(message->base.descriptor == &gg110_send_message__descriptor);
- return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
-size_t gg110_send_message__pack_to_buffer
- (const GG110SendMessage *message,
- ProtobufCBuffer *buffer)
- assert(message->base.descriptor == &gg110_send_message__descriptor);
- return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
- gg110_send_message__unpack
- (ProtobufCAllocator *allocator,
- return (GG110SendMessage *)
- protobuf_c_message_unpack (&gg110_send_message__descriptor,
-void gg110_send_message__free_unpacked
- (GG110SendMessage *message,
- ProtobufCAllocator *allocator)
- assert(message->base.descriptor == &gg110_send_message__descriptor);
- protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
-void gg110_imtoken__init
- (GG110Imtoken *message)
- static GG110Imtoken init_value = GG110_IMTOKEN__INIT;
-size_t gg110_imtoken__get_packed_size
- (const GG110Imtoken *message)
- assert(message->base.descriptor == &gg110_imtoken__descriptor);
- return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
-size_t gg110_imtoken__pack
- (const GG110Imtoken *message,
- assert(message->base.descriptor == &gg110_imtoken__descriptor);
- return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
-size_t gg110_imtoken__pack_to_buffer
- (const GG110Imtoken *message,
- ProtobufCBuffer *buffer)
- assert(message->base.descriptor == &gg110_imtoken__descriptor);
- return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
- (ProtobufCAllocator *allocator,
- return (GG110Imtoken *)
- protobuf_c_message_unpack (&gg110_imtoken__descriptor,
-void gg110_imtoken__free_unpacked
- (GG110Imtoken *message,
- ProtobufCAllocator *allocator)
- assert(message->base.descriptor == &gg110_imtoken__descriptor);
- protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
-void gg110_chat_info_update__init
- (GG110ChatInfoUpdate *message)
- static GG110ChatInfoUpdate init_value = GG110_CHAT_INFO_UPDATE__INIT;
-size_t gg110_chat_info_update__get_packed_size
- (const GG110ChatInfoUpdate *message)
- assert(message->base.descriptor == &gg110_chat_info_update__descriptor);
- return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
-size_t gg110_chat_info_update__pack
- (const GG110ChatInfoUpdate *message,
- assert(message->base.descriptor == &gg110_chat_info_update__descriptor);
- return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
-size_t gg110_chat_info_update__pack_to_buffer
- (const GG110ChatInfoUpdate *message,
- ProtobufCBuffer *buffer)
- assert(message->base.descriptor == &gg110_chat_info_update__descriptor);
- return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
- gg110_chat_info_update__unpack
- (ProtobufCAllocator *allocator,
- return (GG110ChatInfoUpdate *)
- protobuf_c_message_unpack (&gg110_chat_info_update__descriptor,
-void gg110_chat_info_update__free_unpacked
- (GG110ChatInfoUpdate *message,
- ProtobufCAllocator *allocator)
- assert(message->base.descriptor == &gg110_chat_info_update__descriptor);
- protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
- static ProtobufKVP init_value = PROTOBUF_KVP__INIT;
-size_t protobuf_kvp__get_packed_size
- (const ProtobufKVP *message)
- assert(message->base.descriptor == &protobuf_kvp__descriptor);
- return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
-size_t protobuf_kvp__pack
- (const ProtobufKVP *message,
- assert(message->base.descriptor == &protobuf_kvp__descriptor);
- return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
-size_t protobuf_kvp__pack_to_buffer
- (const ProtobufKVP *message,
- ProtobufCBuffer *buffer)
- assert(message->base.descriptor == &protobuf_kvp__descriptor);
- return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
- (ProtobufCAllocator *allocator,
- protobuf_c_message_unpack (&protobuf_kvp__descriptor,
-void protobuf_kvp__free_unpacked
- ProtobufCAllocator *allocator)
- assert(message->base.descriptor == &protobuf_kvp__descriptor);
- protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
-void gg110_options__init
- (GG110Options *message)
- static GG110Options init_value = GG110_OPTIONS__INIT;
-size_t gg110_options__get_packed_size
- (const GG110Options *message)
- assert(message->base.descriptor == &gg110_options__descriptor);
- return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
-size_t gg110_options__pack
- (const GG110Options *message,
- assert(message->base.descriptor == &gg110_options__descriptor);
- return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
-size_t gg110_options__pack_to_buffer
- (const GG110Options *message,
- ProtobufCBuffer *buffer)
- assert(message->base.descriptor == &gg110_options__descriptor);
- return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
- (ProtobufCAllocator *allocator,
- return (GG110Options *)
- protobuf_c_message_unpack (&gg110_options__descriptor,
-void gg110_options__free_unpacked
- (GG110Options *message,
- ProtobufCAllocator *allocator)
- assert(message->base.descriptor == &gg110_options__descriptor);
- protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
-void gg110_access_info__init
- (GG110AccessInfo *message)
- static GG110AccessInfo init_value = GG110_ACCESS_INFO__INIT;
-size_t gg110_access_info__get_packed_size
- (const GG110AccessInfo *message)
- assert(message->base.descriptor == &gg110_access_info__descriptor);
- return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
-size_t gg110_access_info__pack
- (const GG110AccessInfo *message,
- assert(message->base.descriptor == &gg110_access_info__descriptor);
- return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
-size_t gg110_access_info__pack_to_buffer
- (const GG110AccessInfo *message,
- ProtobufCBuffer *buffer)
- assert(message->base.descriptor == &gg110_access_info__descriptor);
- return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
- gg110_access_info__unpack
- (ProtobufCAllocator *allocator,
- return (GG110AccessInfo *)
- protobuf_c_message_unpack (&gg110_access_info__descriptor,
-void gg110_access_info__free_unpacked
- (GG110AccessInfo *message,
- ProtobufCAllocator *allocator)
- assert(message->base.descriptor == &gg110_access_info__descriptor);
- protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
-void gg112_transfer_info_uin__init
- (GG112TransferInfoUin *message)
- static GG112TransferInfoUin init_value = GG112_TRANSFER_INFO_UIN__INIT;
-size_t gg112_transfer_info_uin__get_packed_size
- (const GG112TransferInfoUin *message)
- assert(message->base.descriptor == &gg112_transfer_info_uin__descriptor);
- return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
-size_t gg112_transfer_info_uin__pack
- (const GG112TransferInfoUin *message,
- assert(message->base.descriptor == &gg112_transfer_info_uin__descriptor);
- return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
-size_t gg112_transfer_info_uin__pack_to_buffer
- (const GG112TransferInfoUin *message,
- ProtobufCBuffer *buffer)
- assert(message->base.descriptor == &gg112_transfer_info_uin__descriptor);
- return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
- gg112_transfer_info_uin__unpack
- (ProtobufCAllocator *allocator,
- return (GG112TransferInfoUin *)
- protobuf_c_message_unpack (&gg112_transfer_info_uin__descriptor,
-void gg112_transfer_info_uin__free_unpacked
- (GG112TransferInfoUin *message,
- ProtobufCAllocator *allocator)
- assert(message->base.descriptor == &gg112_transfer_info_uin__descriptor);
- protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
-void gg112_transfer_info_file__init
- (GG112TransferInfoFile *message)
- static GG112TransferInfoFile init_value = GG112_TRANSFER_INFO_FILE__INIT;
-size_t gg112_transfer_info_file__get_packed_size
- (const GG112TransferInfoFile *message)
- assert(message->base.descriptor == &gg112_transfer_info_file__descriptor);
- return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
-size_t gg112_transfer_info_file__pack
- (const GG112TransferInfoFile *message,
- assert(message->base.descriptor == &gg112_transfer_info_file__descriptor);
- return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
-size_t gg112_transfer_info_file__pack_to_buffer
- (const GG112TransferInfoFile *message,
- ProtobufCBuffer *buffer)
- assert(message->base.descriptor == &gg112_transfer_info_file__descriptor);
- return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
- gg112_transfer_info_file__unpack
- (ProtobufCAllocator *allocator,
- return (GG112TransferInfoFile *)
- protobuf_c_message_unpack (&gg112_transfer_info_file__descriptor,
-void gg112_transfer_info_file__free_unpacked
- (GG112TransferInfoFile *message,
- ProtobufCAllocator *allocator)
- assert(message->base.descriptor == &gg112_transfer_info_file__descriptor);
- protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
-void gg112_transfer_info__init
- (GG112TransferInfo *message)
- static GG112TransferInfo init_value = GG112_TRANSFER_INFO__INIT;
-size_t gg112_transfer_info__get_packed_size
- (const GG112TransferInfo *message)
- assert(message->base.descriptor == &gg112_transfer_info__descriptor);
- return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
-size_t gg112_transfer_info__pack
- (const GG112TransferInfo *message,
- assert(message->base.descriptor == &gg112_transfer_info__descriptor);
- return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
-size_t gg112_transfer_info__pack_to_buffer
- (const GG112TransferInfo *message,
- ProtobufCBuffer *buffer)
- assert(message->base.descriptor == &gg112_transfer_info__descriptor);
- return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
- gg112_transfer_info__unpack
- (ProtobufCAllocator *allocator,
- return (GG112TransferInfo *)
- protobuf_c_message_unpack (&gg112_transfer_info__descriptor,
-void gg112_transfer_info__free_unpacked
- (GG112TransferInfo *message,
- ProtobufCAllocator *allocator)
- assert(message->base.descriptor == &gg112_transfer_info__descriptor);
- protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
-void gg110_magic_notification__init
- (GG110MagicNotification *message)
- static GG110MagicNotification init_value = GG110_MAGIC_NOTIFICATION__INIT;
-size_t gg110_magic_notification__get_packed_size
- (const GG110MagicNotification *message)
- assert(message->base.descriptor == &gg110_magic_notification__descriptor);
- return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
-size_t gg110_magic_notification__pack
- (const GG110MagicNotification *message,
- assert(message->base.descriptor == &gg110_magic_notification__descriptor);
- return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
-size_t gg110_magic_notification__pack_to_buffer
- (const GG110MagicNotification *message,
- ProtobufCBuffer *buffer)
- assert(message->base.descriptor == &gg110_magic_notification__descriptor);
- return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
-GG110MagicNotification *
- gg110_magic_notification__unpack
- (ProtobufCAllocator *allocator,
- return (GG110MagicNotification *)
- protobuf_c_message_unpack (&gg110_magic_notification__descriptor,
-void gg110_magic_notification__free_unpacked
- (GG110MagicNotification *message,
- ProtobufCAllocator *allocator)
- assert(message->base.descriptor == &gg110_magic_notification__descriptor);
- protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
-static const int32_t gg110_login_ok__dummy1__default_value = 1;
-static const ProtobufCFieldDescriptor gg110_login_ok__field_descriptors[4] =
- PROTOBUF_C_LABEL_REQUIRED,
- 0, /* quantifier_offset */
- offsetof(GG110LoginOK, dummy1),
- &gg110_login_ok__dummy1__default_value,
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_STRING,
- 0, /* quantifier_offset */
- offsetof(GG110LoginOK, dummyhash),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_UINT32,
- 0, /* quantifier_offset */
- offsetof(GG110LoginOK, uin),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_FIXED32,
- 0, /* quantifier_offset */
- offsetof(GG110LoginOK, server_time),
- 0,NULL,NULL /* reserved1,reserved2, etc */
-static const unsigned gg110_login_ok__field_indices_by_name[] = {
- 0, /* field[0] = dummy1 */
- 1, /* field[1] = dummyhash */
- 3, /* field[3] = server_time */
- 2, /* field[2] = uin */
-static const ProtobufCIntRange gg110_login_ok__number_ranges[1 + 1] =
-const ProtobufCMessageDescriptor gg110_login_ok__descriptor =
- PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
- gg110_login_ok__field_descriptors,
- gg110_login_ok__field_indices_by_name,
- 1, gg110_login_ok__number_ranges,
- (ProtobufCMessageInit) gg110_login_ok__init,
- NULL,NULL,NULL /* reserved[123] */
-static const ProtobufCFieldDescriptor gg110_pong__field_descriptors[1] =
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_FIXED32,
- 0, /* quantifier_offset */
- offsetof(GG110Pong, server_time),
- 0,NULL,NULL /* reserved1,reserved2, etc */
-static const unsigned gg110_pong__field_indices_by_name[] = {
- 0, /* field[0] = server_time */
-static const ProtobufCIntRange gg110_pong__number_ranges[1 + 1] =
-const ProtobufCMessageDescriptor gg110_pong__descriptor =
- PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
- gg110_pong__field_descriptors,
- gg110_pong__field_indices_by_name,
- 1, gg110_pong__number_ranges,
- (ProtobufCMessageInit) gg110_pong__init,
- NULL,NULL,NULL /* reserved[123] */
-const ProtobufCEnumValue gg110_ack__type__enum_values_by_number[6] =
- { "MSG", "GG110_ACK__TYPE__MSG", 1 },
- { "CHAT", "GG110_ACK__TYPE__CHAT", 2 },
- { "CHAT_INFO", "GG110_ACK__TYPE__CHAT_INFO", 3 },
- { "MAGIC_NOTIFICATION", "GG110_ACK__TYPE__MAGIC_NOTIFICATION", 5 },
- { "MPA", "GG110_ACK__TYPE__MPA", 6 },
- { "TRANSFER_INFO", "GG110_ACK__TYPE__TRANSFER_INFO", 7 },
-static const ProtobufCIntRange gg110_ack__type__value_ranges[] = {
-const ProtobufCEnumValueIndex gg110_ack__type__enum_values_by_name[6] =
- { "MAGIC_NOTIFICATION", 3 },
- { "TRANSFER_INFO", 5 },
-const ProtobufCEnumDescriptor gg110_ack__type__descriptor =
- PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC,
- gg110_ack__type__enum_values_by_number,
- gg110_ack__type__enum_values_by_name,
- gg110_ack__type__value_ranges,
- NULL,NULL,NULL,NULL /* reserved[1234] */
-static const uint32_t gg110_ack__dummy1__default_value = 1u;
-static const ProtobufCFieldDescriptor gg110_ack__field_descriptors[3] =
- PROTOBUF_C_LABEL_REQUIRED,
- 0, /* quantifier_offset */
- offsetof(GG110Ack, type),
- &gg110_ack__type__descriptor,
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_UINT32,
- 0, /* quantifier_offset */
- offsetof(GG110Ack, seq),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_UINT32,
- 0, /* quantifier_offset */
- offsetof(GG110Ack, dummy1),
- &gg110_ack__dummy1__default_value,
- 0,NULL,NULL /* reserved1,reserved2, etc */
-static const unsigned gg110_ack__field_indices_by_name[] = {
- 2, /* field[2] = dummy1 */
- 1, /* field[1] = seq */
- 0, /* field[0] = type */
-static const ProtobufCIntRange gg110_ack__number_ranges[1 + 1] =
-const ProtobufCMessageDescriptor gg110_ack__descriptor =
- PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
- gg110_ack__field_descriptors,
- gg110_ack__field_indices_by_name,
- 1, gg110_ack__number_ranges,
- (ProtobufCMessageInit) gg110_ack__init,
- NULL,NULL,NULL /* reserved[123] */
-char gg105_login__initial_descr__default_value[] = "";
-static const uint32_t gg105_login__initial_status__default_value = 8227u;
-static const int32_t gg105_login__dummy1__default_value = 4;
-static const uint32_t gg105_login__dummy2__default_value = 65994615u;
-static const uint32_t gg105_login__dummy3__default_value = 198164u;
-static const int32_t gg105_login__dummy5__default_value = 255;
-static const int32_t gg105_login__dummy6__default_value = 100;
-static const uint32_t gg105_login__dummy7__default_value = 127u;
-static const int32_t gg105_login__dummy8__default_value = 0;
-static const uint32_t gg105_login__dummy10__default_value = 0u;
-static const ProtobufCFieldDescriptor gg105_login__field_descriptors[16] =
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_STRING,
- 0, /* quantifier_offset */
- offsetof(GG105Login, lang),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- 0, /* quantifier_offset */
- offsetof(GG105Login, uin),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- 0, /* quantifier_offset */
- offsetof(GG105Login, hash),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- 0, /* quantifier_offset */
- offsetof(GG105Login, dummy1),
- &gg105_login__dummy1__default_value,
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_FIXED32,
- 0, /* quantifier_offset */
- offsetof(GG105Login, dummy2),
- &gg105_login__dummy2__default_value,
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_FIXED32,
- 0, /* quantifier_offset */
- offsetof(GG105Login, dummy3),
- &gg105_login__dummy3__default_value,
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_STRING,
- 0, /* quantifier_offset */
- offsetof(GG105Login, client),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_FIXED32,
- 0, /* quantifier_offset */
- offsetof(GG105Login, initial_status),
- &gg105_login__initial_status__default_value,
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_STRING,
- 0, /* quantifier_offset */
- offsetof(GG105Login, initial_descr),
- &gg105_login__initial_descr__default_value,
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- 0, /* quantifier_offset */
- offsetof(GG105Login, dummy4),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_STRING,
- 0, /* quantifier_offset */
- offsetof(GG105Login, supported_features),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- 0, /* quantifier_offset */
- offsetof(GG105Login, dummy5),
- &gg105_login__dummy5__default_value,
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- 0, /* quantifier_offset */
- offsetof(GG105Login, dummy6),
- &gg105_login__dummy6__default_value,
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_OPTIONAL,
- PROTOBUF_C_TYPE_FIXED32,
- offsetof(GG105Login, has_dummy7),
- offsetof(GG105Login, dummy7),
- &gg105_login__dummy7__default_value,
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_OPTIONAL,
- offsetof(GG105Login, has_dummy8),
- offsetof(GG105Login, dummy8),
- &gg105_login__dummy8__default_value,
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_OPTIONAL,
- PROTOBUF_C_TYPE_UINT32,
- offsetof(GG105Login, has_dummy10),
- offsetof(GG105Login, dummy10),
- &gg105_login__dummy10__default_value,
- 0,NULL,NULL /* reserved1,reserved2, etc */
-static const unsigned gg105_login__field_indices_by_name[] = {
- 6, /* field[6] = client */
- 3, /* field[3] = dummy1 */
- 15, /* field[15] = dummy10 */
- 4, /* field[4] = dummy2 */
- 5, /* field[5] = dummy3 */
- 9, /* field[9] = dummy4 */
- 11, /* field[11] = dummy5 */
- 12, /* field[12] = dummy6 */
- 13, /* field[13] = dummy7 */
- 14, /* field[14] = dummy8 */
- 2, /* field[2] = hash */
- 8, /* field[8] = initial_descr */
- 7, /* field[7] = initial_status */
- 0, /* field[0] = lang */
- 10, /* field[10] = supported_features */
- 1, /* field[1] = uin */
-static const ProtobufCIntRange gg105_login__number_ranges[2 + 1] =
-const ProtobufCMessageDescriptor gg105_login__descriptor =
- PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
- gg105_login__field_descriptors,
- gg105_login__field_indices_by_name,
- 2, gg105_login__number_ranges,
- (ProtobufCMessageInit) gg105_login__init,
- NULL,NULL,NULL /* reserved[123] */
-static const ProtobufCFieldDescriptor gg110_message_ack_link__field_descriptors[2] =
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_FIXED64,
- 0, /* quantifier_offset */
- offsetof(GG110MessageAckLink, id),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_STRING,
- 0, /* quantifier_offset */
- offsetof(GG110MessageAckLink, url),
- 0,NULL,NULL /* reserved1,reserved2, etc */
-static const unsigned gg110_message_ack_link__field_indices_by_name[] = {
- 1, /* field[1] = url */
-static const ProtobufCIntRange gg110_message_ack_link__number_ranges[1 + 1] =
-const ProtobufCMessageDescriptor gg110_message_ack_link__descriptor =
- PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
- sizeof(GG110MessageAckLink),
- gg110_message_ack_link__field_descriptors,
- gg110_message_ack_link__field_indices_by_name,
- 1, gg110_message_ack_link__number_ranges,
- (ProtobufCMessageInit) gg110_message_ack_link__init,
- NULL,NULL,NULL /* reserved[123] */
-static const uint32_t gg110_message_ack__dummy1__default_value = 0u;
-static const ProtobufCFieldDescriptor gg110_message_ack__field_descriptors[7] =
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_UINT32,
- 0, /* quantifier_offset */
- offsetof(GG110MessageAck, msg_type),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_UINT32,
- 0, /* quantifier_offset */
- offsetof(GG110MessageAck, seq),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_FIXED32,
- 0, /* quantifier_offset */
- offsetof(GG110MessageAck, time),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_OPTIONAL,
- PROTOBUF_C_TYPE_FIXED64,
- offsetof(GG110MessageAck, has_msg_id),
- offsetof(GG110MessageAck, msg_id),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_OPTIONAL,
- PROTOBUF_C_TYPE_FIXED64,
- offsetof(GG110MessageAck, has_conv_id),
- offsetof(GG110MessageAck, conv_id),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REPEATED,
- PROTOBUF_C_TYPE_MESSAGE,
- offsetof(GG110MessageAck, n_links),
- offsetof(GG110MessageAck, links),
- &gg110_message_ack_link__descriptor,
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_UINT32,
- 0, /* quantifier_offset */
- offsetof(GG110MessageAck, dummy1),
- &gg110_message_ack__dummy1__default_value,
- 0,NULL,NULL /* reserved1,reserved2, etc */
-static const unsigned gg110_message_ack__field_indices_by_name[] = {
- 4, /* field[4] = conv_id */
- 6, /* field[6] = dummy1 */
- 5, /* field[5] = links */
- 3, /* field[3] = msg_id */
- 0, /* field[0] = msg_type */
- 1, /* field[1] = seq */
- 2, /* field[2] = time */
-static const ProtobufCIntRange gg110_message_ack__number_ranges[1 + 1] =
-const ProtobufCMessageDescriptor gg110_message_ack__descriptor =
- PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
- sizeof(GG110MessageAck),
- gg110_message_ack__field_descriptors,
- gg110_message_ack__field_indices_by_name,
- 1, gg110_message_ack__number_ranges,
- (ProtobufCMessageInit) gg110_message_ack__init,
- NULL,NULL,NULL /* reserved[123] */
-const ProtobufCEnumValue gg110_event__type__enum_values_by_number[2] =
- { "XML", "GG110_EVENT__TYPE__XML", 0 },
- { "JSON", "GG110_EVENT__TYPE__JSON", 2 },
-static const ProtobufCIntRange gg110_event__type__value_ranges[] = {
-const ProtobufCEnumValueIndex gg110_event__type__enum_values_by_name[2] =
-const ProtobufCEnumDescriptor gg110_event__type__descriptor =
- PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC,
- gg110_event__type__enum_values_by_number,
- gg110_event__type__enum_values_by_name,
- gg110_event__type__value_ranges,
- NULL,NULL,NULL,NULL /* reserved[1234] */
-static const ProtobufCFieldDescriptor gg110_event__field_descriptors[5] =
- PROTOBUF_C_LABEL_REQUIRED,
- 0, /* quantifier_offset */
- offsetof(GG110Event, type),
- &gg110_event__type__descriptor,
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_UINT32,
- 0, /* quantifier_offset */
- offsetof(GG110Event, seq),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_STRING,
- 0, /* quantifier_offset */
- offsetof(GG110Event, data),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_STRING,
- 0, /* quantifier_offset */
- offsetof(GG110Event, subtype),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_OPTIONAL,
- PROTOBUF_C_TYPE_UINT64,
- offsetof(GG110Event, has_id),
- offsetof(GG110Event, id),
- 0,NULL,NULL /* reserved1,reserved2, etc */
-static const unsigned gg110_event__field_indices_by_name[] = {
- 2, /* field[2] = data */
- 1, /* field[1] = seq */
- 3, /* field[3] = subtype */
- 0, /* field[0] = type */
-static const ProtobufCIntRange gg110_event__number_ranges[1 + 1] =
-const ProtobufCMessageDescriptor gg110_event__descriptor =
- PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
- gg110_event__field_descriptors,
- gg110_event__field_indices_by_name,
- 1, gg110_event__number_ranges,
- (ProtobufCMessageInit) gg110_event__init,
- NULL,NULL,NULL /* reserved[123] */
-char gg110_recv_message__msg_plain__default_value[] = "";
-static const ProtobufCFieldDescriptor gg110_recv_message__field_descriptors[10] =
- PROTOBUF_C_LABEL_OPTIONAL,
- offsetof(GG110RecvMessage, has_sender),
- offsetof(GG110RecvMessage, sender),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_UINT32,
- 0, /* quantifier_offset */
- offsetof(GG110RecvMessage, flags),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_UINT32,
- 0, /* quantifier_offset */
- offsetof(GG110RecvMessage, seq),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_FIXED32,
- 0, /* quantifier_offset */
- offsetof(GG110RecvMessage, time),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_STRING,
- 0, /* quantifier_offset */
- offsetof(GG110RecvMessage, msg_plain),
- &gg110_recv_message__msg_plain__default_value,
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_OPTIONAL,
- PROTOBUF_C_TYPE_STRING,
- 0, /* quantifier_offset */
- offsetof(GG110RecvMessage, msg_xhtml),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_OPTIONAL,
- offsetof(GG110RecvMessage, has_data),
- offsetof(GG110RecvMessage, data),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_OPTIONAL,
- PROTOBUF_C_TYPE_FIXED64,
- offsetof(GG110RecvMessage, has_msg_id),
- offsetof(GG110RecvMessage, msg_id),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_OPTIONAL,
- PROTOBUF_C_TYPE_FIXED64,
- offsetof(GG110RecvMessage, has_chat_id),
- offsetof(GG110RecvMessage, chat_id),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_OPTIONAL,
- PROTOBUF_C_TYPE_FIXED64,
- offsetof(GG110RecvMessage, has_conv_id),
- offsetof(GG110RecvMessage, conv_id),
- 0,NULL,NULL /* reserved1,reserved2, etc */
-static const unsigned gg110_recv_message__field_indices_by_name[] = {
- 8, /* field[8] = chat_id */
- 9, /* field[9] = conv_id */
- 6, /* field[6] = data */
- 1, /* field[1] = flags */
- 7, /* field[7] = msg_id */
- 4, /* field[4] = msg_plain */
- 5, /* field[5] = msg_xhtml */
- 0, /* field[0] = sender */
- 2, /* field[2] = seq */
- 3, /* field[3] = time */
-static const ProtobufCIntRange gg110_recv_message__number_ranges[2 + 1] =
-const ProtobufCMessageDescriptor gg110_recv_message__descriptor =
- PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
- sizeof(GG110RecvMessage),
- gg110_recv_message__field_descriptors,
- gg110_recv_message__field_indices_by_name,
- 2, gg110_recv_message__number_ranges,
- (ProtobufCMessageInit) gg110_recv_message__init,
- NULL,NULL,NULL /* reserved[123] */
-char gg110_send_message__dummy3__default_value[] = "";
-static const uint32_t gg110_send_message__dummy1__default_value = 8u;
-static const ProtobufCFieldDescriptor gg110_send_message__field_descriptors[7] =
- PROTOBUF_C_LABEL_OPTIONAL,
- offsetof(GG110SendMessage, has_recipient),
- offsetof(GG110SendMessage, recipient),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_UINT32,
- 0, /* quantifier_offset */
- offsetof(GG110SendMessage, dummy1),
- &gg110_send_message__dummy1__default_value,
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_UINT32,
- 0, /* quantifier_offset */
- offsetof(GG110SendMessage, seq),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_STRING,
- 0, /* quantifier_offset */
- offsetof(GG110SendMessage, msg_plain),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_STRING,
- 0, /* quantifier_offset */
- offsetof(GG110SendMessage, msg_xhtml),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_OPTIONAL,
- PROTOBUF_C_TYPE_STRING,
- 0, /* quantifier_offset */
- offsetof(GG110SendMessage, dummy3),
- &gg110_send_message__dummy3__default_value,
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_OPTIONAL,
- PROTOBUF_C_TYPE_FIXED64,
- offsetof(GG110SendMessage, has_chat_id),
- offsetof(GG110SendMessage, chat_id),
- 0,NULL,NULL /* reserved1,reserved2, etc */
-static const unsigned gg110_send_message__field_indices_by_name[] = {
- 6, /* field[6] = chat_id */
- 1, /* field[1] = dummy1 */
- 5, /* field[5] = dummy3 */
- 3, /* field[3] = msg_plain */
- 4, /* field[4] = msg_xhtml */
- 0, /* field[0] = recipient */
- 2, /* field[2] = seq */
-static const ProtobufCIntRange gg110_send_message__number_ranges[3 + 1] =
-const ProtobufCMessageDescriptor gg110_send_message__descriptor =
- PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
- sizeof(GG110SendMessage),
- gg110_send_message__field_descriptors,
- gg110_send_message__field_indices_by_name,
- 3, gg110_send_message__number_ranges,
- (ProtobufCMessageInit) gg110_send_message__init,
- NULL,NULL,NULL /* reserved[123] */
-static const ProtobufCFieldDescriptor gg110_imtoken__field_descriptors[1] =
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_STRING,
- 0, /* quantifier_offset */
- offsetof(GG110Imtoken, imtoken),
- 0,NULL,NULL /* reserved1,reserved2, etc */
-static const unsigned gg110_imtoken__field_indices_by_name[] = {
- 0, /* field[0] = imtoken */
-static const ProtobufCIntRange gg110_imtoken__number_ranges[1 + 1] =
-const ProtobufCMessageDescriptor gg110_imtoken__descriptor =
- PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
- gg110_imtoken__field_descriptors,
- gg110_imtoken__field_indices_by_name,
- 1, gg110_imtoken__number_ranges,
- (ProtobufCMessageInit) gg110_imtoken__init,
- NULL,NULL,NULL /* reserved[123] */
-static const ProtobufCFieldDescriptor gg110_chat_info_update__field_descriptors[10] =
- PROTOBUF_C_LABEL_REQUIRED,
- 0, /* quantifier_offset */
- offsetof(GG110ChatInfoUpdate, participant),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- 0, /* quantifier_offset */
- offsetof(GG110ChatInfoUpdate, inviter),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_FIXED32,
- 0, /* quantifier_offset */
- offsetof(GG110ChatInfoUpdate, update_type),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_FIXED32,
- 0, /* quantifier_offset */
- offsetof(GG110ChatInfoUpdate, time),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_FIXED32,
- 0, /* quantifier_offset */
- offsetof(GG110ChatInfoUpdate, dummy1),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_UINT32,
- 0, /* quantifier_offset */
- offsetof(GG110ChatInfoUpdate, version),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_UINT32,
- 0, /* quantifier_offset */
- offsetof(GG110ChatInfoUpdate, dummy2),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_FIXED64,
- 0, /* quantifier_offset */
- offsetof(GG110ChatInfoUpdate, msg_id),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_FIXED64,
- 0, /* quantifier_offset */
- offsetof(GG110ChatInfoUpdate, chat_id),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_FIXED64,
- 0, /* quantifier_offset */
- offsetof(GG110ChatInfoUpdate, conv_id),
- 0,NULL,NULL /* reserved1,reserved2, etc */
-static const unsigned gg110_chat_info_update__field_indices_by_name[] = {
- 8, /* field[8] = chat_id */
- 9, /* field[9] = conv_id */
- 4, /* field[4] = dummy1 */
- 6, /* field[6] = dummy2 */
- 1, /* field[1] = inviter */
- 7, /* field[7] = msg_id */
- 0, /* field[0] = participant */
- 3, /* field[3] = time */
- 2, /* field[2] = update_type */
- 5, /* field[5] = version */
-static const ProtobufCIntRange gg110_chat_info_update__number_ranges[2 + 1] =
-const ProtobufCMessageDescriptor gg110_chat_info_update__descriptor =
- PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
- sizeof(GG110ChatInfoUpdate),
- gg110_chat_info_update__field_descriptors,
- gg110_chat_info_update__field_indices_by_name,
- 2, gg110_chat_info_update__number_ranges,
- (ProtobufCMessageInit) gg110_chat_info_update__init,
- NULL,NULL,NULL /* reserved[123] */
-static const ProtobufCFieldDescriptor protobuf_kvp__field_descriptors[2] =
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_STRING,
- 0, /* quantifier_offset */
- offsetof(ProtobufKVP, key),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_STRING,
- 0, /* quantifier_offset */
- offsetof(ProtobufKVP, value),
- 0,NULL,NULL /* reserved1,reserved2, etc */
-static const unsigned protobuf_kvp__field_indices_by_name[] = {
- 0, /* field[0] = key */
- 1, /* field[1] = value */
-static const ProtobufCIntRange protobuf_kvp__number_ranges[1 + 1] =
-const ProtobufCMessageDescriptor protobuf_kvp__descriptor =
- PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
- protobuf_kvp__field_descriptors,
- protobuf_kvp__field_indices_by_name,
- 1, protobuf_kvp__number_ranges,
- (ProtobufCMessageInit) protobuf_kvp__init,
- NULL,NULL,NULL /* reserved[123] */
-static const uint32_t gg110_options__dummy1__default_value = 0u;
-static const ProtobufCFieldDescriptor gg110_options__field_descriptors[2] =
- PROTOBUF_C_LABEL_REPEATED,
- PROTOBUF_C_TYPE_MESSAGE,
- offsetof(GG110Options, n_options),
- offsetof(GG110Options, options),
- &protobuf_kvp__descriptor,
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_UINT32,
- 0, /* quantifier_offset */
- offsetof(GG110Options, dummy1),
- &gg110_options__dummy1__default_value,
- 0,NULL,NULL /* reserved1,reserved2, etc */
-static const unsigned gg110_options__field_indices_by_name[] = {
- 1, /* field[1] = dummy1 */
- 0, /* field[0] = options */
-static const ProtobufCIntRange gg110_options__number_ranges[1 + 1] =
-const ProtobufCMessageDescriptor gg110_options__descriptor =
- PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
- gg110_options__field_descriptors,
- gg110_options__field_indices_by_name,
- 1, gg110_options__number_ranges,
- (ProtobufCMessageInit) gg110_options__init,
- NULL,NULL,NULL /* reserved[123] */
-static const uint32_t gg110_access_info__dummy1__default_value = 1u;
-static const ProtobufCFieldDescriptor gg110_access_info__field_descriptors[5] =
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_UINT32,
- 0, /* quantifier_offset */
- offsetof(GG110AccessInfo, dummy1),
- &gg110_access_info__dummy1__default_value,
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_UINT32,
- 0, /* quantifier_offset */
- offsetof(GG110AccessInfo, dummy2),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_UINT32,
- 0, /* quantifier_offset */
- offsetof(GG110AccessInfo, last_message),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_UINT32,
- 0, /* quantifier_offset */
- offsetof(GG110AccessInfo, last_file_transfer),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_UINT32,
- 0, /* quantifier_offset */
- offsetof(GG110AccessInfo, last_conference_ch),
- 0,NULL,NULL /* reserved1,reserved2, etc */
-static const unsigned gg110_access_info__field_indices_by_name[] = {
- 0, /* field[0] = dummy1 */
- 1, /* field[1] = dummy2 */
- 4, /* field[4] = last_conference_ch */
- 3, /* field[3] = last_file_transfer */
- 2, /* field[2] = last_message */
-static const ProtobufCIntRange gg110_access_info__number_ranges[1 + 1] =
-const ProtobufCMessageDescriptor gg110_access_info__descriptor =
- PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
- sizeof(GG110AccessInfo),
- gg110_access_info__field_descriptors,
- gg110_access_info__field_indices_by_name,
- 1, gg110_access_info__number_ranges,
- (ProtobufCMessageInit) gg110_access_info__init,
- NULL,NULL,NULL /* reserved[123] */
-static const uint32_t gg112_transfer_info_uin__dummy1__default_value = 1u;
-static const ProtobufCFieldDescriptor gg112_transfer_info_uin__field_descriptors[2] =
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_UINT32,
- 0, /* quantifier_offset */
- offsetof(GG112TransferInfoUin, dummy1),
- &gg112_transfer_info_uin__dummy1__default_value,
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- 0, /* quantifier_offset */
- offsetof(GG112TransferInfoUin, uin),
- 0,NULL,NULL /* reserved1,reserved2, etc */
-static const unsigned gg112_transfer_info_uin__field_indices_by_name[] = {
- 0, /* field[0] = dummy1 */
- 1, /* field[1] = uin */
-static const ProtobufCIntRange gg112_transfer_info_uin__number_ranges[1 + 1] =
-const ProtobufCMessageDescriptor gg112_transfer_info_uin__descriptor =
- PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
- "GG112TransferInfoUin",
- "GG112TransferInfoUin",
- "GG112TransferInfoUin",
- sizeof(GG112TransferInfoUin),
- gg112_transfer_info_uin__field_descriptors,
- gg112_transfer_info_uin__field_indices_by_name,
- 1, gg112_transfer_info_uin__number_ranges,
- (ProtobufCMessageInit) gg112_transfer_info_uin__init,
- NULL,NULL,NULL /* reserved[123] */
-char gg112_transfer_info_file__type__default_value[] = "other";
-static const ProtobufCFieldDescriptor gg112_transfer_info_file__field_descriptors[6] =
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_STRING,
- 0, /* quantifier_offset */
- offsetof(GG112TransferInfoFile, type),
- &gg112_transfer_info_file__type__default_value,
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_STRING,
- 0, /* quantifier_offset */
- offsetof(GG112TransferInfoFile, url),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_STRING,
- 0, /* quantifier_offset */
- offsetof(GG112TransferInfoFile, content_type),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_STRING,
- 0, /* quantifier_offset */
- offsetof(GG112TransferInfoFile, filename),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_UINT32,
- 0, /* quantifier_offset */
- offsetof(GG112TransferInfoFile, filesize),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_FIXED64,
- 0, /* quantifier_offset */
- offsetof(GG112TransferInfoFile, msg_id),
- 0,NULL,NULL /* reserved1,reserved2, etc */
-static const unsigned gg112_transfer_info_file__field_indices_by_name[] = {
- 2, /* field[2] = content_type */
- 3, /* field[3] = filename */
- 4, /* field[4] = filesize */
- 5, /* field[5] = msg_id */
- 0, /* field[0] = type */
- 1, /* field[1] = url */
-static const ProtobufCIntRange gg112_transfer_info_file__number_ranges[3 + 1] =
-const ProtobufCMessageDescriptor gg112_transfer_info_file__descriptor =
- PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
- "GG112TransferInfoFile",
- "GG112TransferInfoFile",
- "GG112TransferInfoFile",
- sizeof(GG112TransferInfoFile),
- gg112_transfer_info_file__field_descriptors,
- gg112_transfer_info_file__field_indices_by_name,
- 3, gg112_transfer_info_file__number_ranges,
- (ProtobufCMessageInit) gg112_transfer_info_file__init,
- NULL,NULL,NULL /* reserved[123] */
-static const ProtobufCFieldDescriptor gg112_transfer_info__field_descriptors[9] =
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_UINT32,
- 0, /* quantifier_offset */
- offsetof(GG112TransferInfo, dummy1),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_MESSAGE,
- 0, /* quantifier_offset */
- offsetof(GG112TransferInfo, peer),
- &gg112_transfer_info_uin__descriptor,
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_FIXED32,
- 0, /* quantifier_offset */
- offsetof(GG112TransferInfo, time),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_MESSAGE,
- 0, /* quantifier_offset */
- offsetof(GG112TransferInfo, sender),
- &gg112_transfer_info_uin__descriptor,
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REPEATED,
- PROTOBUF_C_TYPE_MESSAGE,
- offsetof(GG112TransferInfo, n_data),
- offsetof(GG112TransferInfo, data),
- &protobuf_kvp__descriptor,
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_OPTIONAL,
- PROTOBUF_C_TYPE_MESSAGE,
- 0, /* quantifier_offset */
- offsetof(GG112TransferInfo, file),
- &gg112_transfer_info_file__descriptor,
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_UINT32,
- 0, /* quantifier_offset */
- offsetof(GG112TransferInfo, seq),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_FIXED64,
- 0, /* quantifier_offset */
- offsetof(GG112TransferInfo, msg_id),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_FIXED64,
- 0, /* quantifier_offset */
- offsetof(GG112TransferInfo, conv_id),
- 0,NULL,NULL /* reserved1,reserved2, etc */
-static const unsigned gg112_transfer_info__field_indices_by_name[] = {
- 8, /* field[8] = conv_id */
- 4, /* field[4] = data */
- 0, /* field[0] = dummy1 */
- 5, /* field[5] = file */
- 7, /* field[7] = msg_id */
- 1, /* field[1] = peer */
- 3, /* field[3] = sender */
- 6, /* field[6] = seq */
- 2, /* field[2] = time */
-static const ProtobufCIntRange gg112_transfer_info__number_ranges[2 + 1] =
-const ProtobufCMessageDescriptor gg112_transfer_info__descriptor =
- PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
- sizeof(GG112TransferInfo),
- gg112_transfer_info__field_descriptors,
- gg112_transfer_info__field_indices_by_name,
- 2, gg112_transfer_info__number_ranges,
- (ProtobufCMessageInit) gg112_transfer_info__init,
- NULL,NULL,NULL /* reserved[123] */
-char gg110_magic_notification__dummy4__default_value[] = "";
-static const int32_t gg110_magic_notification__dummy1__default_value = 2;
-static const int32_t gg110_magic_notification__dummy2__default_value = 1;
-static const int32_t gg110_magic_notification__dummy3__default_value = 1;
-static const ProtobufCFieldDescriptor gg110_magic_notification__field_descriptors[6] =
- PROTOBUF_C_LABEL_REQUIRED,
- 0, /* quantifier_offset */
- offsetof(GG110MagicNotification, dummy1),
- &gg110_magic_notification__dummy1__default_value,
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- 0, /* quantifier_offset */
- offsetof(GG110MagicNotification, seq),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- 0, /* quantifier_offset */
- offsetof(GG110MagicNotification, dummy2),
- &gg110_magic_notification__dummy2__default_value,
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- 0, /* quantifier_offset */
- offsetof(GG110MagicNotification, dummy3),
- &gg110_magic_notification__dummy3__default_value,
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- 0, /* quantifier_offset */
- offsetof(GG110MagicNotification, uin),
- 0,NULL,NULL /* reserved1,reserved2, etc */
- PROTOBUF_C_LABEL_REQUIRED,
- PROTOBUF_C_TYPE_STRING,
- 0, /* quantifier_offset */
- offsetof(GG110MagicNotification, dummy4),
- &gg110_magic_notification__dummy4__default_value,
- 0,NULL,NULL /* reserved1,reserved2, etc */
-static const unsigned gg110_magic_notification__field_indices_by_name[] = {
- 0, /* field[0] = dummy1 */
- 2, /* field[2] = dummy2 */
- 3, /* field[3] = dummy3 */
- 5, /* field[5] = dummy4 */
- 1, /* field[1] = seq */
- 4, /* field[4] = uin */
-static const ProtobufCIntRange gg110_magic_notification__number_ranges[1 + 1] =
-const ProtobufCMessageDescriptor gg110_magic_notification__descriptor =
- PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
- "GG110MagicNotification",
- "GG110MagicNotification",
- "GG110MagicNotification",
- sizeof(GG110MagicNotification),
- gg110_magic_notification__field_descriptors,
- gg110_magic_notification__field_indices_by_name,
- 1, gg110_magic_notification__number_ranges,
- (ProtobufCMessageInit) gg110_magic_notification__init,
- NULL,NULL,NULL /* reserved[123] */
--- a/libpurple/protocols/gg/lib/packets.pb-c.h Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,766 +0,0 @@
-/* Generated by the protocol buffer compiler. DO NOT EDIT! */
-/* Generated from: packets.proto */
-#ifndef PROTOBUF_C_packets_2eproto__INCLUDED
-#define PROTOBUF_C_packets_2eproto__INCLUDED
-#if PROTOBUF_C_VERSION_NUMBER < 1000000
-# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers.
-#elif 1000002 < PROTOBUF_C_MIN_COMPILER_VERSION
-# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c.
-typedef struct _GG110LoginOK GG110LoginOK;
-typedef struct _GG110Pong GG110Pong;
-typedef struct _GG110Ack GG110Ack;
-typedef struct _GG105Login GG105Login;
-typedef struct _GG110MessageAckLink GG110MessageAckLink;
-typedef struct _GG110MessageAck GG110MessageAck;
-typedef struct _GG110Event GG110Event;
-typedef struct _GG110RecvMessage GG110RecvMessage;
-typedef struct _GG110SendMessage GG110SendMessage;
-typedef struct _GG110Imtoken GG110Imtoken;
-typedef struct _GG110ChatInfoUpdate GG110ChatInfoUpdate;
-typedef struct _ProtobufKVP ProtobufKVP;
-typedef struct _GG110Options GG110Options;
-typedef struct _GG110AccessInfo GG110AccessInfo;
-typedef struct _GG112TransferInfoUin GG112TransferInfoUin;
-typedef struct _GG112TransferInfoFile GG112TransferInfoFile;
-typedef struct _GG112TransferInfo GG112TransferInfo;
-typedef struct _GG110MagicNotification GG110MagicNotification;
-typedef enum _GG110Ack__Type {
- GG110_ACK__TYPE__MSG = 1,
- GG110_ACK__TYPE__CHAT = 2,
- GG110_ACK__TYPE__CHAT_INFO = 3,
- GG110_ACK__TYPE__MAGIC_NOTIFICATION = 5,
- GG110_ACK__TYPE__MPA = 6,
- GG110_ACK__TYPE__TRANSFER_INFO = 7
- PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(GG110_ACK__TYPE)
-typedef enum _GG110Event__Type {
- GG110_EVENT__TYPE__XML = 0,
- GG110_EVENT__TYPE__JSON = 2
- PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(GG110_EVENT__TYPE)
-#define GG110_LOGIN_OK__INIT \
- { PROTOBUF_C_MESSAGE_INIT (&gg110_login_ok__descriptor) \
-#define GG110_PONG__INIT \
- { PROTOBUF_C_MESSAGE_INIT (&gg110_pong__descriptor) \
-#define GG110_ACK__INIT \
- { PROTOBUF_C_MESSAGE_INIT (&gg110_ack__descriptor) \
- ProtobufCBinaryData uin;
- ProtobufCBinaryData hash;
- uint32_t initial_status;
- char *supported_features;
- ProtobufCBinaryData dummy4;
- protobuf_c_boolean has_dummy7;
- protobuf_c_boolean has_dummy8;
- protobuf_c_boolean has_dummy10;
-extern char gg105_login__initial_descr__default_value[];
-#define GG105_LOGIN__INIT \
- { PROTOBUF_C_MESSAGE_INIT (&gg105_login__descriptor) \
- , NULL, {0,NULL}, {0,NULL}, NULL, 8227u, gg105_login__initial_descr__default_value, NULL, 4, 65994615u, 198164u, {0,NULL}, 255, 100, 0,127u, 0,0, 0,0u }
-struct _GG110MessageAckLink
-#define GG110_MESSAGE_ACK_LINK__INIT \
- { PROTOBUF_C_MESSAGE_INIT (&gg110_message_ack_link__descriptor) \
- protobuf_c_boolean has_msg_id;
- protobuf_c_boolean has_conv_id;
- GG110MessageAckLink **links;
-#define GG110_MESSAGE_ACK__INIT \
- { PROTOBUF_C_MESSAGE_INIT (&gg110_message_ack__descriptor) \
- , 0, 0, 0, 0,0, 0,0, 0,NULL, 0u }
- protobuf_c_boolean has_id;
-#define GG110_EVENT__INIT \
- { PROTOBUF_C_MESSAGE_INIT (&gg110_event__descriptor) \
- , 0, 0, NULL, NULL, 0,0 }
-struct _GG110RecvMessage
- protobuf_c_boolean has_sender;
- ProtobufCBinaryData sender;
- protobuf_c_boolean has_data;
- ProtobufCBinaryData data;
- protobuf_c_boolean has_msg_id;
- protobuf_c_boolean has_chat_id;
- protobuf_c_boolean has_conv_id;
-extern char gg110_recv_message__msg_plain__default_value[];
-#define GG110_RECV_MESSAGE__INIT \
- { PROTOBUF_C_MESSAGE_INIT (&gg110_recv_message__descriptor) \
- , 0,{0,NULL}, 0, 0, 0, gg110_recv_message__msg_plain__default_value, NULL, 0,{0,NULL}, 0,0, 0,0, 0,0 }
-struct _GG110SendMessage
- protobuf_c_boolean has_recipient;
- ProtobufCBinaryData recipient;
- protobuf_c_boolean has_chat_id;
-extern char gg110_send_message__dummy3__default_value[];
-#define GG110_SEND_MESSAGE__INIT \
- { PROTOBUF_C_MESSAGE_INIT (&gg110_send_message__descriptor) \
- , 0,{0,NULL}, 8u, 0, NULL, NULL, gg110_send_message__dummy3__default_value, 0,0 }
-#define GG110_IMTOKEN__INIT \
- { PROTOBUF_C_MESSAGE_INIT (&gg110_imtoken__descriptor) \
-struct _GG110ChatInfoUpdate
- ProtobufCBinaryData participant;
- ProtobufCBinaryData inviter;
-#define GG110_CHAT_INFO_UPDATE__INIT \
- { PROTOBUF_C_MESSAGE_INIT (&gg110_chat_info_update__descriptor) \
- , {0,NULL}, {0,NULL}, 0, 0, 0, 0, 0, 0, 0, 0 }
-#define PROTOBUF_KVP__INIT \
- { PROTOBUF_C_MESSAGE_INIT (&protobuf_kvp__descriptor) \
-#define GG110_OPTIONS__INIT \
- { PROTOBUF_C_MESSAGE_INIT (&gg110_options__descriptor) \
- uint32_t last_file_transfer;
- uint32_t last_conference_ch;
-#define GG110_ACCESS_INFO__INIT \
- { PROTOBUF_C_MESSAGE_INIT (&gg110_access_info__descriptor) \
-struct _GG112TransferInfoUin
- ProtobufCBinaryData uin;
-#define GG112_TRANSFER_INFO_UIN__INIT \
- { PROTOBUF_C_MESSAGE_INIT (&gg112_transfer_info_uin__descriptor) \
-struct _GG112TransferInfoFile
-extern char gg112_transfer_info_file__type__default_value[];
-#define GG112_TRANSFER_INFO_FILE__INIT \
- { PROTOBUF_C_MESSAGE_INIT (&gg112_transfer_info_file__descriptor) \
- , gg112_transfer_info_file__type__default_value, NULL, NULL, NULL, 0, 0 }
-struct _GG112TransferInfo
- GG112TransferInfoUin *peer;
- GG112TransferInfoUin *sender;
- GG112TransferInfoFile *file;
-#define GG112_TRANSFER_INFO__INIT \
- { PROTOBUF_C_MESSAGE_INIT (&gg112_transfer_info__descriptor) \
- , 0, NULL, NULL, 0, 0,NULL, NULL, 0, 0, 0 }
-struct _GG110MagicNotification
- ProtobufCBinaryData uin;
-extern char gg110_magic_notification__dummy4__default_value[];
-#define GG110_MAGIC_NOTIFICATION__INIT \
- { PROTOBUF_C_MESSAGE_INIT (&gg110_magic_notification__descriptor) \
- , 2, 0, 1, 1, {0,NULL}, gg110_magic_notification__dummy4__default_value }
-/* GG110LoginOK methods */
-void gg110_login_ok__init
- (GG110LoginOK *message);
-size_t gg110_login_ok__get_packed_size
- (const GG110LoginOK *message);
-size_t gg110_login_ok__pack
- (const GG110LoginOK *message,
-size_t gg110_login_ok__pack_to_buffer
- (const GG110LoginOK *message,
- ProtobufCBuffer *buffer);
- (ProtobufCAllocator *allocator,
-void gg110_login_ok__free_unpacked
- (GG110LoginOK *message,
- ProtobufCAllocator *allocator);
-size_t gg110_pong__get_packed_size
- (const GG110Pong *message);
- (const GG110Pong *message,
-size_t gg110_pong__pack_to_buffer
- (const GG110Pong *message,
- ProtobufCBuffer *buffer);
- (ProtobufCAllocator *allocator,
-void gg110_pong__free_unpacked
- ProtobufCAllocator *allocator);
-size_t gg110_ack__get_packed_size
- (const GG110Ack *message);
- (const GG110Ack *message,
-size_t gg110_ack__pack_to_buffer
- (const GG110Ack *message,
- ProtobufCBuffer *buffer);
- (ProtobufCAllocator *allocator,
-void gg110_ack__free_unpacked
- ProtobufCAllocator *allocator);
-/* GG105Login methods */
-size_t gg105_login__get_packed_size
- (const GG105Login *message);
-size_t gg105_login__pack
- (const GG105Login *message,
-size_t gg105_login__pack_to_buffer
- (const GG105Login *message,
- ProtobufCBuffer *buffer);
- (ProtobufCAllocator *allocator,
-void gg105_login__free_unpacked
- ProtobufCAllocator *allocator);
-/* GG110MessageAckLink methods */
-void gg110_message_ack_link__init
- (GG110MessageAckLink *message);
-size_t gg110_message_ack_link__get_packed_size
- (const GG110MessageAckLink *message);
-size_t gg110_message_ack_link__pack
- (const GG110MessageAckLink *message,
-size_t gg110_message_ack_link__pack_to_buffer
- (const GG110MessageAckLink *message,
- ProtobufCBuffer *buffer);
- gg110_message_ack_link__unpack
- (ProtobufCAllocator *allocator,
-void gg110_message_ack_link__free_unpacked
- (GG110MessageAckLink *message,
- ProtobufCAllocator *allocator);
-/* GG110MessageAck methods */
-void gg110_message_ack__init
- (GG110MessageAck *message);
-size_t gg110_message_ack__get_packed_size
- (const GG110MessageAck *message);
-size_t gg110_message_ack__pack
- (const GG110MessageAck *message,
-size_t gg110_message_ack__pack_to_buffer
- (const GG110MessageAck *message,
- ProtobufCBuffer *buffer);
- gg110_message_ack__unpack
- (ProtobufCAllocator *allocator,
-void gg110_message_ack__free_unpacked
- (GG110MessageAck *message,
- ProtobufCAllocator *allocator);
-/* GG110Event methods */
-size_t gg110_event__get_packed_size
- (const GG110Event *message);
-size_t gg110_event__pack
- (const GG110Event *message,
-size_t gg110_event__pack_to_buffer
- (const GG110Event *message,
- ProtobufCBuffer *buffer);
- (ProtobufCAllocator *allocator,
-void gg110_event__free_unpacked
- ProtobufCAllocator *allocator);
-/* GG110RecvMessage methods */
-void gg110_recv_message__init
- (GG110RecvMessage *message);
-size_t gg110_recv_message__get_packed_size
- (const GG110RecvMessage *message);
-size_t gg110_recv_message__pack
- (const GG110RecvMessage *message,
-size_t gg110_recv_message__pack_to_buffer
- (const GG110RecvMessage *message,
- ProtobufCBuffer *buffer);
- gg110_recv_message__unpack
- (ProtobufCAllocator *allocator,
-void gg110_recv_message__free_unpacked
- (GG110RecvMessage *message,
- ProtobufCAllocator *allocator);
-/* GG110SendMessage methods */
-void gg110_send_message__init
- (GG110SendMessage *message);
-size_t gg110_send_message__get_packed_size
- (const GG110SendMessage *message);
-size_t gg110_send_message__pack
- (const GG110SendMessage *message,
-size_t gg110_send_message__pack_to_buffer
- (const GG110SendMessage *message,
- ProtobufCBuffer *buffer);
- gg110_send_message__unpack
- (ProtobufCAllocator *allocator,
-void gg110_send_message__free_unpacked
- (GG110SendMessage *message,
- ProtobufCAllocator *allocator);
-/* GG110Imtoken methods */
-void gg110_imtoken__init
- (GG110Imtoken *message);
-size_t gg110_imtoken__get_packed_size
- (const GG110Imtoken *message);
-size_t gg110_imtoken__pack
- (const GG110Imtoken *message,
-size_t gg110_imtoken__pack_to_buffer
- (const GG110Imtoken *message,
- ProtobufCBuffer *buffer);
- (ProtobufCAllocator *allocator,
-void gg110_imtoken__free_unpacked
- (GG110Imtoken *message,
- ProtobufCAllocator *allocator);
-/* GG110ChatInfoUpdate methods */
-void gg110_chat_info_update__init
- (GG110ChatInfoUpdate *message);
-size_t gg110_chat_info_update__get_packed_size
- (const GG110ChatInfoUpdate *message);
-size_t gg110_chat_info_update__pack
- (const GG110ChatInfoUpdate *message,
-size_t gg110_chat_info_update__pack_to_buffer
- (const GG110ChatInfoUpdate *message,
- ProtobufCBuffer *buffer);
- gg110_chat_info_update__unpack
- (ProtobufCAllocator *allocator,
-void gg110_chat_info_update__free_unpacked
- (GG110ChatInfoUpdate *message,
- ProtobufCAllocator *allocator);
-/* ProtobufKVP methods */
- (ProtobufKVP *message);
-size_t protobuf_kvp__get_packed_size
- (const ProtobufKVP *message);
-size_t protobuf_kvp__pack
- (const ProtobufKVP *message,
-size_t protobuf_kvp__pack_to_buffer
- (const ProtobufKVP *message,
- ProtobufCBuffer *buffer);
- (ProtobufCAllocator *allocator,
-void protobuf_kvp__free_unpacked
- ProtobufCAllocator *allocator);
-/* GG110Options methods */
-void gg110_options__init
- (GG110Options *message);
-size_t gg110_options__get_packed_size
- (const GG110Options *message);
-size_t gg110_options__pack
- (const GG110Options *message,
-size_t gg110_options__pack_to_buffer
- (const GG110Options *message,
- ProtobufCBuffer *buffer);
- (ProtobufCAllocator *allocator,
-void gg110_options__free_unpacked
- (GG110Options *message,
- ProtobufCAllocator *allocator);
-/* GG110AccessInfo methods */
-void gg110_access_info__init
- (GG110AccessInfo *message);
-size_t gg110_access_info__get_packed_size
- (const GG110AccessInfo *message);
-size_t gg110_access_info__pack
- (const GG110AccessInfo *message,
-size_t gg110_access_info__pack_to_buffer
- (const GG110AccessInfo *message,
- ProtobufCBuffer *buffer);
- gg110_access_info__unpack
- (ProtobufCAllocator *allocator,
-void gg110_access_info__free_unpacked
- (GG110AccessInfo *message,
- ProtobufCAllocator *allocator);
-/* GG112TransferInfoUin methods */
-void gg112_transfer_info_uin__init
- (GG112TransferInfoUin *message);
-size_t gg112_transfer_info_uin__get_packed_size
- (const GG112TransferInfoUin *message);
-size_t gg112_transfer_info_uin__pack
- (const GG112TransferInfoUin *message,
-size_t gg112_transfer_info_uin__pack_to_buffer
- (const GG112TransferInfoUin *message,
- ProtobufCBuffer *buffer);
- gg112_transfer_info_uin__unpack
- (ProtobufCAllocator *allocator,
-void gg112_transfer_info_uin__free_unpacked
- (GG112TransferInfoUin *message,
- ProtobufCAllocator *allocator);
-/* GG112TransferInfoFile methods */
-void gg112_transfer_info_file__init
- (GG112TransferInfoFile *message);
-size_t gg112_transfer_info_file__get_packed_size
- (const GG112TransferInfoFile *message);
-size_t gg112_transfer_info_file__pack
- (const GG112TransferInfoFile *message,
-size_t gg112_transfer_info_file__pack_to_buffer
- (const GG112TransferInfoFile *message,
- ProtobufCBuffer *buffer);
- gg112_transfer_info_file__unpack
- (ProtobufCAllocator *allocator,
-void gg112_transfer_info_file__free_unpacked
- (GG112TransferInfoFile *message,
- ProtobufCAllocator *allocator);
-/* GG112TransferInfo methods */
-void gg112_transfer_info__init
- (GG112TransferInfo *message);
-size_t gg112_transfer_info__get_packed_size
- (const GG112TransferInfo *message);
-size_t gg112_transfer_info__pack
- (const GG112TransferInfo *message,
-size_t gg112_transfer_info__pack_to_buffer
- (const GG112TransferInfo *message,
- ProtobufCBuffer *buffer);
- gg112_transfer_info__unpack
- (ProtobufCAllocator *allocator,
-void gg112_transfer_info__free_unpacked
- (GG112TransferInfo *message,
- ProtobufCAllocator *allocator);
-/* GG110MagicNotification methods */
-void gg110_magic_notification__init
- (GG110MagicNotification *message);
-size_t gg110_magic_notification__get_packed_size
- (const GG110MagicNotification *message);
-size_t gg110_magic_notification__pack
- (const GG110MagicNotification *message,
-size_t gg110_magic_notification__pack_to_buffer
- (const GG110MagicNotification *message,
- ProtobufCBuffer *buffer);
-GG110MagicNotification *
- gg110_magic_notification__unpack
- (ProtobufCAllocator *allocator,
-void gg110_magic_notification__free_unpacked
- (GG110MagicNotification *message,
- ProtobufCAllocator *allocator);
-/* --- per-message closures --- */
-typedef void (*GG110LoginOK_Closure)
- (const GG110LoginOK *message,
-typedef void (*GG110Pong_Closure)
- (const GG110Pong *message,
-typedef void (*GG110Ack_Closure)
- (const GG110Ack *message,
-typedef void (*GG105Login_Closure)
- (const GG105Login *message,
-typedef void (*GG110MessageAckLink_Closure)
- (const GG110MessageAckLink *message,
-typedef void (*GG110MessageAck_Closure)
- (const GG110MessageAck *message,
-typedef void (*GG110Event_Closure)
- (const GG110Event *message,
-typedef void (*GG110RecvMessage_Closure)
- (const GG110RecvMessage *message,
-typedef void (*GG110SendMessage_Closure)
- (const GG110SendMessage *message,
-typedef void (*GG110Imtoken_Closure)
- (const GG110Imtoken *message,
-typedef void (*GG110ChatInfoUpdate_Closure)
- (const GG110ChatInfoUpdate *message,
-typedef void (*ProtobufKVP_Closure)
- (const ProtobufKVP *message,
-typedef void (*GG110Options_Closure)
- (const GG110Options *message,
-typedef void (*GG110AccessInfo_Closure)
- (const GG110AccessInfo *message,
-typedef void (*GG112TransferInfoUin_Closure)
- (const GG112TransferInfoUin *message,
-typedef void (*GG112TransferInfoFile_Closure)
- (const GG112TransferInfoFile *message,
-typedef void (*GG112TransferInfo_Closure)
- (const GG112TransferInfo *message,
-typedef void (*GG110MagicNotification_Closure)
- (const GG110MagicNotification *message,
-/* --- descriptors --- */
-extern const ProtobufCMessageDescriptor gg110_login_ok__descriptor;
-extern const ProtobufCMessageDescriptor gg110_pong__descriptor;
-extern const ProtobufCMessageDescriptor gg110_ack__descriptor;
-extern const ProtobufCEnumDescriptor gg110_ack__type__descriptor;
-extern const ProtobufCMessageDescriptor gg105_login__descriptor;
-extern const ProtobufCMessageDescriptor gg110_message_ack_link__descriptor;
-extern const ProtobufCMessageDescriptor gg110_message_ack__descriptor;
-extern const ProtobufCMessageDescriptor gg110_event__descriptor;
-extern const ProtobufCEnumDescriptor gg110_event__type__descriptor;
-extern const ProtobufCMessageDescriptor gg110_recv_message__descriptor;
-extern const ProtobufCMessageDescriptor gg110_send_message__descriptor;
-extern const ProtobufCMessageDescriptor gg110_imtoken__descriptor;
-extern const ProtobufCMessageDescriptor gg110_chat_info_update__descriptor;
-extern const ProtobufCMessageDescriptor protobuf_kvp__descriptor;
-extern const ProtobufCMessageDescriptor gg110_options__descriptor;
-extern const ProtobufCMessageDescriptor gg110_access_info__descriptor;
-extern const ProtobufCMessageDescriptor gg112_transfer_info_uin__descriptor;
-extern const ProtobufCMessageDescriptor gg112_transfer_info_file__descriptor;
-extern const ProtobufCMessageDescriptor gg112_transfer_info__descriptor;
-extern const ProtobufCMessageDescriptor gg110_magic_notification__descriptor;
-#endif /* PROTOBUF_C_packets_2eproto__INCLUDED */
--- a/libpurple/protocols/gg/lib/protobuf-c.c Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,3288 +0,0 @@
- * Copyright (c) 2008-2014, Dave Benson and the protobuf-c authors.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- * Support library for `protoc-c` generated code.
- * This file implements the public API used by the code generated
- * \authors Dave Benson and the protobuf-c authors
- * \copyright 2008-2014. Licensed under the terms of the [BSD-2-Clause] license.
- * \todo 64-BIT OPTIMIZATION: certain implementations use 32-bit math
- * even on 64-bit platforms (uint64_size, uint64_pack, parse_uint64).
- * \todo Use size_t consistently.
-#include <stdlib.h> /* for malloc, free */
-#include <string.h> /* for strcmp, strlen, memcpy, memmove, memset */
-/* Pull WORDS_BIGENDIAN etc */
-#define PROTOBUF_C__ASSERT_NOT_REACHED() assert(0)
-/* Workaround for Microsoft compilers. */
-# define inline __inline
- * \defgroup internal Internal functions and macros
- * These are not exported by the library but are useful to developers working
- * on `libprotobuf-c` itself.
- * \defgroup macros Utility macros for manipulating structures
- * Macros and constants used to manipulate the base "classes" generated by
- * `protobuf-c`. They also define limits and check correctness.
-/** The maximum length of a 64-bit integer in varint encoding. */
-#define MAX_UINT64_ENCODED_SIZE 10
-#ifndef PROTOBUF_C_UNPACK_ERROR
-# define PROTOBUF_C_UNPACK_ERROR(...)
- * Internal `ProtobufCMessage` manipulation macro.
- * Base macro for manipulating a `ProtobufCMessage`. Used by STRUCT_MEMBER() and
-#define STRUCT_MEMBER_P(struct_p, struct_offset) \
- ((void *) ((uint8_t *) (struct_p) + (struct_offset)))
- * Return field in a `ProtobufCMessage` based on offset.
- * Take a pointer to a `ProtobufCMessage` and find the field at the offset.
- * Cast it to the passed type.
-#define STRUCT_MEMBER(member_type, struct_p, struct_offset) \
- (*(member_type *) STRUCT_MEMBER_P((struct_p), (struct_offset)))
- * Return field in a `ProtobufCMessage` based on offset.
- * Take a pointer to a `ProtobufCMessage` and find the field at the offset. Cast
- * it to a pointer to the passed type.
-#define STRUCT_MEMBER_PTR(member_type, struct_p, struct_offset) \
- ((member_type *) STRUCT_MEMBER_P((struct_p), (struct_offset)))
-/* Assertions for magic numbers. */
-#define ASSERT_IS_ENUM_DESCRIPTOR(desc) \
- assert((desc)->magic == PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC)
-#define ASSERT_IS_MESSAGE_DESCRIPTOR(desc) \
- assert((desc)->magic == PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC)
-#define ASSERT_IS_MESSAGE(message) \
- ASSERT_IS_MESSAGE_DESCRIPTOR((message)->descriptor)
-#define ASSERT_IS_SERVICE_DESCRIPTOR(desc) \
- assert((desc)->magic == PROTOBUF_C__SERVICE_DESCRIPTOR_MAGIC)
-protobuf_c_version(void)
- return PROTOBUF_C_VERSION;
-protobuf_c_version_number(void)
- return PROTOBUF_C_VERSION_NUMBER;
-system_alloc(void *allocator_data, size_t size)
-system_free(void *allocator_data, void *data)
-do_alloc(ProtobufCAllocator *allocator, size_t size)
- return allocator->alloc(allocator->allocator_data, size);
-do_free(ProtobufCAllocator *allocator, void *data)
- allocator->free(allocator->allocator_data, data);
- * This allocator uses the system's malloc() and free(). It is the default
- * allocator used if NULL is passed as the ProtobufCAllocator to an exported
-static ProtobufCAllocator protobuf_c__allocator = {
- .alloc = &system_alloc,
- .allocator_data = NULL,
-/* === buffer-simple === */
-protobuf_c_buffer_simple_append(ProtobufCBuffer *buffer,
- size_t len, const uint8_t *data)
- ProtobufCBufferSimple *simp = (ProtobufCBufferSimple *) buffer;
- size_t new_len = simp->len + len;
- if (new_len > simp->alloced) {
- ProtobufCAllocator *allocator = simp->allocator;
- size_t new_alloced = simp->alloced * 2;
- allocator = &protobuf_c__allocator;
- while (new_alloced < new_len)
- new_alloced += new_alloced;
- new_data = do_alloc(allocator, new_alloced);
- memcpy(new_data, simp->data, simp->len);
- if (simp->must_free_data)
- do_free(allocator, simp->data);
- simp->must_free_data = TRUE;
- simp->alloced = new_alloced;
- memcpy(simp->data + simp->len, data, len);
- * \defgroup packedsz protobuf_c_message_get_packed_size() implementation
- * Routines mainly used by protobuf_c_message_get_packed_size().
- * Return the number of bytes required to store the tag for the field. Includes
- * 3 bits for the wire-type, and a single bit that denotes the end-of-tag.
- * Number of bytes required.
-get_tag_size(unsigned number)
- if (number < (1 << 4)) {
- } else if (number < (1 << 11)) {
- } else if (number < (1 << 18)) {
- } else if (number < (1 << 25)) {
- * Return the number of bytes required to store a variable-length unsigned
- * 32-bit integer in base-128 varint encoding.
- * Number of bytes required.
- } else if (v < (1 << 14)) {
- } else if (v < (1 << 21)) {
- } else if (v < (1 << 28)) {
- * Return the number of bytes required to store a variable-length signed 32-bit
- * integer in base-128 varint encoding.
- * Number of bytes required.
- } else if (v < (1 << 7)) {
- } else if (v < (1 << 14)) {
- } else if (v < (1 << 21)) {
- } else if (v < (1 << 28)) {
- * Return the ZigZag-encoded 32-bit unsigned integer form of a 32-bit signed
- * ZigZag encoded integer.
- return ((uint32_t) (-v)) * 2 - 1;
- * Return the number of bytes required to store a signed 32-bit integer,
- * converted to an unsigned 32-bit integer with ZigZag encoding, using base-128
- * Number of bytes required.
- return uint32_size(zigzag32(v));
- * Return the number of bytes required to store a 64-bit unsigned integer in
- * base-128 varint encoding.
- * Number of bytes required.
- uint32_t upper_v = (uint32_t) (v >> 32);
- return uint32_size((uint32_t) v);
- } else if (upper_v < (1 << 3)) {
- } else if (upper_v < (1 << 10)) {
- } else if (upper_v < (1 << 17)) {
- } else if (upper_v < (1 << 24)) {
- } else if (upper_v < (1U << 31)) {
- * Return the ZigZag-encoded 64-bit unsigned integer form of a 64-bit signed
- * ZigZag encoded integer.
- return ((uint64_t) (-v)) * 2 - 1;
- * Return the number of bytes required to store a signed 64-bit integer,
- * converted to an unsigned 64-bit integer with ZigZag encoding, using base-128
- * Number of bytes required.
- return uint64_size(zigzag64(v));
- * Calculate the serialized size of a single required message field, including
- * the space needed by the preceding tag.
- * Field descriptor for member.
- * Number of bytes required.
-required_field_get_packed_size(const ProtobufCFieldDescriptor *field,
- size_t rv = get_tag_size(field->id);
- case PROTOBUF_C_TYPE_SINT32:
- return rv + sint32_size(*(const int32_t *) member);
- case PROTOBUF_C_TYPE_INT32:
- return rv + int32_size(*(const uint32_t *) member);
- case PROTOBUF_C_TYPE_UINT32:
- return rv + uint32_size(*(const uint32_t *) member);
- case PROTOBUF_C_TYPE_SINT64:
- return rv + sint64_size(*(const int64_t *) member);
- case PROTOBUF_C_TYPE_INT64:
- case PROTOBUF_C_TYPE_UINT64:
- return rv + uint64_size(*(const uint64_t *) member);
- case PROTOBUF_C_TYPE_SFIXED32:
- case PROTOBUF_C_TYPE_FIXED32:
- case PROTOBUF_C_TYPE_SFIXED64:
- case PROTOBUF_C_TYPE_FIXED64:
- case PROTOBUF_C_TYPE_BOOL:
- case PROTOBUF_C_TYPE_FLOAT:
- case PROTOBUF_C_TYPE_DOUBLE:
- case PROTOBUF_C_TYPE_ENUM:
- /* \todo Is this correct for negative-valued enums? */
- return rv + uint32_size(*(const uint32_t *) member);
- case PROTOBUF_C_TYPE_STRING: {
- const char *str = *(char * const *) member;
- size_t len = str ? strlen(str) : 0;
- return rv + uint32_size(len) + len;
- case PROTOBUF_C_TYPE_BYTES: {
- size_t len = ((const ProtobufCBinaryData *) member)->len;
- return rv + uint32_size(len) + len;
- case PROTOBUF_C_TYPE_MESSAGE: {
- const ProtobufCMessage *msg = *(ProtobufCMessage * const *) member;
- size_t subrv = msg ? protobuf_c_message_get_packed_size(msg) : 0;
- return rv + uint32_size(subrv) + subrv;
- PROTOBUF_C__ASSERT_NOT_REACHED();
- * Calculate the serialized size of a single optional message field, including
- * the space needed by the preceding tag. Returns 0 if the optional field isn't
- * Field descriptor for member.
- * True if the field exists, false if not.
- * Number of bytes required.
-optional_field_get_packed_size(const ProtobufCFieldDescriptor *field,
- const protobuf_c_boolean *has,
- if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
- field->type == PROTOBUF_C_TYPE_STRING)
- const void *ptr = *(const void * const *) member;
- if (ptr == NULL || ptr == field->default_value)
- return required_field_get_packed_size(field, member);
- * Calculate the serialized size of repeated message fields, which may consist
- * of any number of values (including 0). Includes the space needed by the
- * preceding tags (as needed).
- * Field descriptor for member.
- * Number of repeated field members.
- * Number of bytes required.
-repeated_field_get_packed_size(const ProtobufCFieldDescriptor *field,
- size_t count, const void *member)
- void *array = *(void * const *) member;
- header_size = get_tag_size(field->id);
- if (0 == (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED))
- case PROTOBUF_C_TYPE_SINT32:
- for (i = 0; i < count; i++)
- rv += sint32_size(((int32_t *) array)[i]);
- case PROTOBUF_C_TYPE_INT32:
- for (i = 0; i < count; i++)
- rv += int32_size(((uint32_t *) array)[i]);
- case PROTOBUF_C_TYPE_UINT32:
- case PROTOBUF_C_TYPE_ENUM:
- for (i = 0; i < count; i++)
- rv += uint32_size(((uint32_t *) array)[i]);
- case PROTOBUF_C_TYPE_SINT64:
- for (i = 0; i < count; i++)
- rv += sint64_size(((int64_t *) array)[i]);
- case PROTOBUF_C_TYPE_INT64:
- case PROTOBUF_C_TYPE_UINT64:
- for (i = 0; i < count; i++)
- rv += uint64_size(((uint64_t *) array)[i]);
- case PROTOBUF_C_TYPE_SFIXED32:
- case PROTOBUF_C_TYPE_FIXED32:
- case PROTOBUF_C_TYPE_FLOAT:
- case PROTOBUF_C_TYPE_SFIXED64:
- case PROTOBUF_C_TYPE_FIXED64:
- case PROTOBUF_C_TYPE_DOUBLE:
- case PROTOBUF_C_TYPE_BOOL:
- case PROTOBUF_C_TYPE_STRING:
- for (i = 0; i < count; i++) {
- size_t len = strlen(((char **) array)[i]);
- rv += uint32_size(len) + len;
- case PROTOBUF_C_TYPE_BYTES:
- for (i = 0; i < count; i++) {
- size_t len = ((ProtobufCBinaryData *) array)[i].len;
- rv += uint32_size(len) + len;
- case PROTOBUF_C_TYPE_MESSAGE:
- for (i = 0; i < count; i++) {
- size_t len = protobuf_c_message_get_packed_size(
- ((ProtobufCMessage **) array)[i]);
- rv += uint32_size(len) + len;
- if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED))
- header_size += uint32_size(rv);
- return header_size + rv;
- * Calculate the serialized size of an unknown field, i.e. one that is passed
- * through mostly uninterpreted. This is required for forward compatibility if
- * new fields are added to the message descriptor.
- * Number of bytes required.
-unknown_field_get_packed_size(const ProtobufCMessageUnknownField *field)
- return get_tag_size(field->tag) + field->len;
- * Calculate the serialized size of the message.
-size_t protobuf_c_message_get_packed_size(const ProtobufCMessage *message)
- ASSERT_IS_MESSAGE(message);
- for (i = 0; i < message->descriptor->n_fields; i++) {
- const ProtobufCFieldDescriptor *field =
- message->descriptor->fields + i;
- ((const char *) message) + field->offset;
- ((const char *) message) + field->quantifier_offset;
- if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
- rv += required_field_get_packed_size(field, member);
- } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) {
- rv += optional_field_get_packed_size(field, qmember, member);
- rv += repeated_field_get_packed_size(
- *(const size_t *) qmember,
- for (i = 0; i < message->n_unknown_fields; i++)
- rv += unknown_field_get_packed_size(&message->unknown_fields[i]);
- * \defgroup pack protobuf_c_message_pack() implementation
- * Routines mainly used by protobuf_c_message_pack().
- * Pack an unsigned 32-bit integer in base-128 varint encoding and return the
- * number of bytes written, which must be 5 or less.
- * Number of bytes written to `out`.
-uint32_pack(uint32_t value, uint8_t *out)
- out[rv++] = value | 0x80;
- out[rv++] = value | 0x80;
- out[rv++] = value | 0x80;
- out[rv++] = value | 0x80;
- /* assert: value<128 */
- * Pack a signed 32-bit integer and return the number of bytes written.
- * Negative numbers are encoded as two's complement 64-bit integers.
- * Number of bytes written to `out`.
-int32_pack(int32_t value, uint8_t *out)
- out[1] = (value >> 7) | 0x80;
- out[2] = (value >> 14) | 0x80;
- out[3] = (value >> 21) | 0x80;
- out[4] = (value >> 28) | 0x80;
- out[5] = out[6] = out[7] = out[8] = 0xff;
- return uint32_pack(value, out);
- * Pack a signed 32-bit integer using ZigZag encoding and return the number of
- * Number of bytes written to `out`.
-sint32_pack(int32_t value, uint8_t *out)
- return uint32_pack(zigzag32(value), out);
- * Pack a 64-bit unsigned integer using base-128 varint encoding and return the
- * number of bytes written.
- * Number of bytes written to `out`.
-uint64_pack(uint64_t value, uint8_t *out)
- uint32_t hi = (uint32_t) (value >> 32);
- uint32_t lo = (uint32_t) value;
- return uint32_pack((uint32_t) lo, out);
- out[1] = (lo >> 7) | 0x80;
- out[2] = (lo >> 14) | 0x80;
- out[3] = (lo >> 21) | 0x80;
- out[4] = (hi << 4) | (lo >> 28);
- out[4] = ((hi & 7) << 4) | (lo >> 28) | 0x80;
- * Pack a 64-bit signed integer in ZigZag encoding and return the number of
- * Number of bytes written to `out`.
-sint64_pack(int64_t value, uint8_t *out)
- return uint64_pack(zigzag64(value), out);
- * Pack a 32-bit quantity in little-endian byte order. Used for protobuf wire
- * types fixed32, sfixed32, float. Similar to "htole32".
- * Number of bytes written to `out`.
-fixed32_pack(uint32_t value, void *out)
-#if !defined(WORDS_BIGENDIAN)
- memcpy(out, &value, 4);
- * Pack a 64-bit quantity in little-endian byte order. Used for protobuf wire
- * types fixed64, sfixed64, double. Similar to "htole64".
- * \todo The big-endian impl is really only good for 32-bit machines, a 64-bit
- * version would be appreciated, plus a way to decide to use 64-bit math where
- * Number of bytes written to `out`.
-fixed64_pack(uint64_t value, void *out)
-#if !defined(WORDS_BIGENDIAN)
- memcpy(out, &value, 8);
- fixed32_pack(value, out);
- fixed32_pack(value >> 32, ((char *) out) + 4);
- * Pack a boolean value as an integer and return the number of bytes written.
- * \todo Perhaps on some platforms *out = !!value would be a better impl, b/c
- * that is idiomatic C++ in some STL implementations.
- * Number of bytes written to `out`.
-boolean_pack(protobuf_c_boolean value, uint8_t *out)
- *out = value ? TRUE : FALSE;
- * Pack a NUL-terminated C string and return the number of bytes written. The
- * output includes a length delimiter.
- * The NULL pointer is treated as an empty string. This isn't really necessary,
- * but it allows people to leave required strings blank. (See Issue #13 in the
- * bug tracker for a little more explanation).
- * Number of bytes written to `out`.
-string_pack(const char *str, uint8_t *out)
- size_t len = strlen(str);
- size_t rv = uint32_pack(len, out);
- memcpy(out + rv, str, len);
- * Pack a ProtobufCBinaryData and return the number of bytes written. The output
- * includes a length delimiter.
- * ProtobufCBinaryData to encode.
- * Number of bytes written to `out`.
-binary_data_pack(const ProtobufCBinaryData *bd, uint8_t *out)
- size_t rv = uint32_pack(len, out);
- memcpy(out + rv, bd->data, len);
- * Pack a ProtobufCMessage and return the number of bytes written. The output
- * includes a length delimiter.
- * ProtobufCMessage object to pack.
- * Number of bytes written to `out`.
-prefixed_message_pack(const ProtobufCMessage *message, uint8_t *out)
- size_t rv = protobuf_c_message_pack(message, out + 1);
- uint32_t rv_packed_size = uint32_size(rv);
- if (rv_packed_size != 1)
- memmove(out + rv_packed_size, out + 1, rv);
- return uint32_pack(rv, out) + rv;
- * Wire-type will be added in required_field_pack().
- * \todo Just call uint64_pack on 64-bit platforms.
- * Number of bytes written to `out`.
-tag_pack(uint32_t id, uint8_t *out)
- if (id < (1 << (32 - 3)))
- return uint32_pack(id << 3, out);
- return uint64_pack(((uint64_t) id) << 3, out);
- * Pack a required field and return the number of bytes written.
- * Number of bytes written to `out`.
-required_field_pack(const ProtobufCFieldDescriptor *field,
- const void *member, uint8_t *out)
- size_t rv = tag_pack(field->id, out);
- case PROTOBUF_C_TYPE_SINT32:
- out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
- return rv + sint32_pack(*(const int32_t *) member, out + rv);
- case PROTOBUF_C_TYPE_INT32:
- out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
- return rv + int32_pack(*(const uint32_t *) member, out + rv);
- case PROTOBUF_C_TYPE_UINT32:
- case PROTOBUF_C_TYPE_ENUM:
- out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
- return rv + uint32_pack(*(const uint32_t *) member, out + rv);
- case PROTOBUF_C_TYPE_SINT64:
- out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
- return rv + sint64_pack(*(const int64_t *) member, out + rv);
- case PROTOBUF_C_TYPE_INT64:
- case PROTOBUF_C_TYPE_UINT64:
- out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
- return rv + uint64_pack(*(const uint64_t *) member, out + rv);
- case PROTOBUF_C_TYPE_SFIXED32:
- case PROTOBUF_C_TYPE_FIXED32:
- case PROTOBUF_C_TYPE_FLOAT:
- out[0] |= PROTOBUF_C_WIRE_TYPE_32BIT;
- return rv + fixed32_pack(*(const uint32_t *) member, out + rv);
- case PROTOBUF_C_TYPE_SFIXED64:
- case PROTOBUF_C_TYPE_FIXED64:
- case PROTOBUF_C_TYPE_DOUBLE:
- out[0] |= PROTOBUF_C_WIRE_TYPE_64BIT;
- return rv + fixed64_pack(*(const uint64_t *) member, out + rv);
- case PROTOBUF_C_TYPE_BOOL:
- out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
- return rv + boolean_pack(*(const protobuf_c_boolean *) member, out + rv);
- case PROTOBUF_C_TYPE_STRING:
- out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
- return rv + string_pack(*(char *const *) member, out + rv);
- case PROTOBUF_C_TYPE_BYTES:
- out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
- return rv + binary_data_pack((const ProtobufCBinaryData *) member, out + rv);
- case PROTOBUF_C_TYPE_MESSAGE:
- out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
- return rv + prefixed_message_pack(*(ProtobufCMessage * const *) member, out + rv);
- PROTOBUF_C__ASSERT_NOT_REACHED();
- * Pack an optional field and return the number of bytes written.
- * Whether the field is set.
- * Number of bytes written to `out`.
-optional_field_pack(const ProtobufCFieldDescriptor *field,
- const protobuf_c_boolean *has,
- const void *member, uint8_t *out)
- if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
- field->type == PROTOBUF_C_TYPE_STRING)
- const void *ptr = *(const void * const *) member;
- if (ptr == NULL || ptr == field->default_value)
- return required_field_pack(field, member, out);
- * Given a field type, return the in-memory size.
- * \todo Implement as a table lookup.
-sizeof_elt_in_repeated_array(ProtobufCType type)
- case PROTOBUF_C_TYPE_SINT32:
- case PROTOBUF_C_TYPE_INT32:
- case PROTOBUF_C_TYPE_UINT32:
- case PROTOBUF_C_TYPE_SFIXED32:
- case PROTOBUF_C_TYPE_FIXED32:
- case PROTOBUF_C_TYPE_FLOAT:
- case PROTOBUF_C_TYPE_ENUM:
- case PROTOBUF_C_TYPE_SINT64:
- case PROTOBUF_C_TYPE_INT64:
- case PROTOBUF_C_TYPE_UINT64:
- case PROTOBUF_C_TYPE_SFIXED64:
- case PROTOBUF_C_TYPE_FIXED64:
- case PROTOBUF_C_TYPE_DOUBLE:
- case PROTOBUF_C_TYPE_BOOL:
- return sizeof(protobuf_c_boolean);
- case PROTOBUF_C_TYPE_STRING:
- case PROTOBUF_C_TYPE_MESSAGE:
- case PROTOBUF_C_TYPE_BYTES:
- return sizeof(ProtobufCBinaryData);
- PROTOBUF_C__ASSERT_NOT_REACHED();
- * Pack an array of 32-bit quantities.
- * Number of elements in the source array.
-copy_to_little_endian_32(void *out, const void *in, const unsigned n)
-#if !defined(WORDS_BIGENDIAN)
- memcpy(out, in, n * 4);
- const uint32_t *ini = in;
- for (i = 0; i < n; i++)
- fixed32_pack(ini[i], (uint32_t *) out + i);
- * Pack an array of 64-bit quantities.
- * Number of elements in the source array.
-copy_to_little_endian_64(void *out, const void *in, const unsigned n)
-#if !defined(WORDS_BIGENDIAN)
- memcpy(out, in, n * 8);
- const uint64_t *ini = in;
- for (i = 0; i < n; i++)
- fixed64_pack(ini[i], (uint64_t *) out + i);
- * Get the minimum number of bytes required to pack a field value of a
-get_type_min_size(ProtobufCType type)
- if (type == PROTOBUF_C_TYPE_SFIXED32 ||
- type == PROTOBUF_C_TYPE_FIXED32 ||
- type == PROTOBUF_C_TYPE_FLOAT)
- if (type == PROTOBUF_C_TYPE_SFIXED64 ||
- type == PROTOBUF_C_TYPE_FIXED64 ||
- type == PROTOBUF_C_TYPE_DOUBLE)
- * Packs the elements of a repeated field and returns the serialised field and
- * Number of elements in the repeated field array.
- * Pointer to the elements for this repeated field.
- * Serialised representation of the repeated field.
- * Number of bytes serialised to `out`.
-repeated_field_pack(const ProtobufCFieldDescriptor *field,
- size_t count, const void *member, uint8_t *out)
- void *array = *(void * const *) member;
- if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) {
- unsigned length_size_min;
- unsigned actual_length_size;
- header_len = tag_pack(field->id, out);
- out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
- len_start = header_len;
- min_length = get_type_min_size(field->type) * count;
- length_size_min = uint32_size(min_length);
- header_len += length_size_min;
- payload_at = out + header_len;
- case PROTOBUF_C_TYPE_SFIXED32:
- case PROTOBUF_C_TYPE_FIXED32:
- case PROTOBUF_C_TYPE_FLOAT:
- copy_to_little_endian_32(payload_at, array, count);
- payload_at += count * 4;
- case PROTOBUF_C_TYPE_SFIXED64:
- case PROTOBUF_C_TYPE_FIXED64:
- case PROTOBUF_C_TYPE_DOUBLE:
- copy_to_little_endian_64(payload_at, array, count);
- payload_at += count * 8;
- case PROTOBUF_C_TYPE_INT32: {
- const int32_t *arr = (const int32_t *) array;
- for (i = 0; i < count; i++)
- payload_at += int32_pack(arr[i], payload_at);
- case PROTOBUF_C_TYPE_SINT32: {
- const int32_t *arr = (const int32_t *) array;
- for (i = 0; i < count; i++)
- payload_at += sint32_pack(arr[i], payload_at);
- case PROTOBUF_C_TYPE_SINT64: {
- const int64_t *arr = (const int64_t *) array;
- for (i = 0; i < count; i++)
- payload_at += sint64_pack(arr[i], payload_at);
- case PROTOBUF_C_TYPE_ENUM:
- case PROTOBUF_C_TYPE_UINT32: {
- const uint32_t *arr = (const uint32_t *) array;
- for (i = 0; i < count; i++)
- payload_at += uint32_pack(arr[i], payload_at);
- case PROTOBUF_C_TYPE_INT64:
- case PROTOBUF_C_TYPE_UINT64: {
- const uint64_t *arr = (const uint64_t *) array;
- for (i = 0; i < count; i++)
- payload_at += uint64_pack(arr[i], payload_at);
- case PROTOBUF_C_TYPE_BOOL: {
- const protobuf_c_boolean *arr = (const protobuf_c_boolean *) array;
- for (i = 0; i < count; i++)
- payload_at += boolean_pack(arr[i], payload_at);
- PROTOBUF_C__ASSERT_NOT_REACHED();
- payload_len = payload_at - (out + header_len);
- actual_length_size = uint32_size(payload_len);
- if (length_size_min != actual_length_size) {
- assert(actual_length_size == length_size_min + 1);
- memmove(out + header_len + 1, out + header_len,
- uint32_pack(payload_len, out + len_start);
- return header_len + payload_len;
- /* not "packed" cased */
- /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */
- unsigned siz = sizeof_elt_in_repeated_array(field->type);
- for (i = 0; i < count; i++) {
- rv += required_field_pack(field, array, out + rv);
- array = (char *)array + siz;
-unknown_field_pack(const ProtobufCMessageUnknownField *field, uint8_t *out)
- size_t rv = tag_pack(field->tag, out);
- out[0] |= field->wire_type;
- memcpy(out + rv, field->data, field->len);
- return rv + field->len;
-protobuf_c_message_pack(const ProtobufCMessage *message, uint8_t *out)
- ASSERT_IS_MESSAGE(message);
- for (i = 0; i < message->descriptor->n_fields; i++) {
- const ProtobufCFieldDescriptor *field =
- message->descriptor->fields + i;
- const void *member = ((const char *) message) + field->offset;
- * It doesn't hurt to compute qmember (a pointer to the
- * quantifier field of the structure), but the pointer is only
- * valid if the field is:
- * - a repeated field, or
- * - an optional field that isn't a pointer type
- * (Meaning: not a message or a string).
- ((const char *) message) + field->quantifier_offset;
- if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
- rv += required_field_pack(field, member, out + rv);
- } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) {
- * Note that qmember is bogus for strings and messages,
- rv += optional_field_pack(field, qmember, member, out + rv);
- rv += repeated_field_pack(field, *(const size_t *) qmember,
- for (i = 0; i < message->n_unknown_fields; i++)
- rv += unknown_field_pack(&message->unknown_fields[i], out + rv);
- * \defgroup packbuf protobuf_c_message_pack_to_buffer() implementation
- * Routines mainly used by protobuf_c_message_pack_to_buffer().
- * Pack a required field to a virtual buffer.
- * The element to be packed.
- * Virtual buffer to append data to.
- * Number of bytes packed.
-required_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
- const void *member, ProtobufCBuffer *buffer)
- uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2];
- rv = tag_pack(field->id, scratch);
- case PROTOBUF_C_TYPE_SINT32:
- scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
- rv += sint32_pack(*(const int32_t *) member, scratch + rv);
- buffer->append(buffer, rv, scratch);
- case PROTOBUF_C_TYPE_INT32:
- scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
- rv += int32_pack(*(const uint32_t *) member, scratch + rv);
- buffer->append(buffer, rv, scratch);
- case PROTOBUF_C_TYPE_UINT32:
- case PROTOBUF_C_TYPE_ENUM:
- scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
- rv += uint32_pack(*(const uint32_t *) member, scratch + rv);
- buffer->append(buffer, rv, scratch);
- case PROTOBUF_C_TYPE_SINT64:
- scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
- rv += sint64_pack(*(const int64_t *) member, scratch + rv);
- buffer->append(buffer, rv, scratch);
- case PROTOBUF_C_TYPE_INT64:
- case PROTOBUF_C_TYPE_UINT64:
- scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
- rv += uint64_pack(*(const uint64_t *) member, scratch + rv);
- buffer->append(buffer, rv, scratch);
- case PROTOBUF_C_TYPE_SFIXED32:
- case PROTOBUF_C_TYPE_FIXED32:
- case PROTOBUF_C_TYPE_FLOAT:
- scratch[0] |= PROTOBUF_C_WIRE_TYPE_32BIT;
- rv += fixed32_pack(*(const uint32_t *) member, scratch + rv);
- buffer->append(buffer, rv, scratch);
- case PROTOBUF_C_TYPE_SFIXED64:
- case PROTOBUF_C_TYPE_FIXED64:
- case PROTOBUF_C_TYPE_DOUBLE:
- scratch[0] |= PROTOBUF_C_WIRE_TYPE_64BIT;
- rv += fixed64_pack(*(const uint64_t *) member, scratch + rv);
- buffer->append(buffer, rv, scratch);
- case PROTOBUF_C_TYPE_BOOL:
- scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
- rv += boolean_pack(*(const protobuf_c_boolean *) member, scratch + rv);
- buffer->append(buffer, rv, scratch);
- case PROTOBUF_C_TYPE_STRING: {
- const char *str = *(char *const *) member;
- size_t sublen = str ? strlen(str) : 0;
- scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
- rv += uint32_pack(sublen, scratch + rv);
- buffer->append(buffer, rv, scratch);
- buffer->append(buffer, sublen, (const uint8_t *) str);
- case PROTOBUF_C_TYPE_BYTES: {
- const ProtobufCBinaryData *bd = ((const ProtobufCBinaryData *) member);
- size_t sublen = bd->len;
- scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
- rv += uint32_pack(sublen, scratch + rv);
- buffer->append(buffer, rv, scratch);
- buffer->append(buffer, sublen, bd->data);
- case PROTOBUF_C_TYPE_MESSAGE: {
- uint8_t simple_buffer_scratch[256];
- const ProtobufCMessage *msg = *(ProtobufCMessage * const *) member;
- ProtobufCBufferSimple simple_buffer =
- PROTOBUF_C_BUFFER_SIMPLE_INIT(simple_buffer_scratch);
- scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
- sublen = protobuf_c_message_pack_to_buffer(msg, &simple_buffer.base);
- rv += uint32_pack(sublen, scratch + rv);
- buffer->append(buffer, rv, scratch);
- buffer->append(buffer, sublen, simple_buffer.data);
- PROTOBUF_C_BUFFER_SIMPLE_CLEAR(&simple_buffer);
- PROTOBUF_C__ASSERT_NOT_REACHED();
- * Pack an optional field to a buffer.
- * Whether the field is set.
- * The element to be packed.
- * Virtual buffer to append data to.
- * Number of bytes serialised to `buffer`.
-optional_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
- const protobuf_c_boolean *has,
- const void *member, ProtobufCBuffer *buffer)
- if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
- field->type == PROTOBUF_C_TYPE_STRING)
- const void *ptr = *(const void *const *) member;
- if (ptr == NULL || ptr == field->default_value)
- return required_field_pack_to_buffer(field, member, buffer);
- * Get the packed size of an array of same field type.
- * Number of elements of this type.
- * The elements to get the size of.
- * Number of bytes required.
-get_packed_payload_length(const ProtobufCFieldDescriptor *field,
- unsigned count, const void *array)
- case PROTOBUF_C_TYPE_SFIXED32:
- case PROTOBUF_C_TYPE_FIXED32:
- case PROTOBUF_C_TYPE_FLOAT:
- case PROTOBUF_C_TYPE_SFIXED64:
- case PROTOBUF_C_TYPE_FIXED64:
- case PROTOBUF_C_TYPE_DOUBLE:
- case PROTOBUF_C_TYPE_INT32: {
- const int32_t *arr = (const int32_t *) array;
- for (i = 0; i < count; i++)
- rv += int32_size(arr[i]);
- case PROTOBUF_C_TYPE_SINT32: {
- const int32_t *arr = (const int32_t *) array;
- for (i = 0; i < count; i++)
- rv += sint32_size(arr[i]);
- case PROTOBUF_C_TYPE_ENUM:
- case PROTOBUF_C_TYPE_UINT32: {
- const uint32_t *arr = (const uint32_t *) array;
- for (i = 0; i < count; i++)
- rv += uint32_size(arr[i]);
- case PROTOBUF_C_TYPE_SINT64: {
- const int64_t *arr = (const int64_t *) array;
- for (i = 0; i < count; i++)
- rv += sint64_size(arr[i]);
- case PROTOBUF_C_TYPE_INT64:
- case PROTOBUF_C_TYPE_UINT64: {
- const uint64_t *arr = (const uint64_t *) array;
- for (i = 0; i < count; i++)
- rv += uint64_size(arr[i]);
- case PROTOBUF_C_TYPE_BOOL:
- PROTOBUF_C__ASSERT_NOT_REACHED();
- * Pack an array of same field type to a virtual buffer.
- * Number of elements of this type.
- * The elements to get the size of.
- * Virtual buffer to append data to.
- * Number of bytes packed.
-pack_buffer_packed_payload(const ProtobufCFieldDescriptor *field,
- unsigned count, const void *array,
- ProtobufCBuffer *buffer)
- case PROTOBUF_C_TYPE_SFIXED32:
- case PROTOBUF_C_TYPE_FIXED32:
- case PROTOBUF_C_TYPE_FLOAT:
-#if !defined(WORDS_BIGENDIAN)
- goto no_packing_needed;
- for (i = 0; i < count; i++) {
- unsigned len = fixed32_pack(((uint32_t *) array)[i], scratch);
- buffer->append(buffer, len, scratch);
- case PROTOBUF_C_TYPE_SFIXED64:
- case PROTOBUF_C_TYPE_FIXED64:
- case PROTOBUF_C_TYPE_DOUBLE:
-#if !defined(WORDS_BIGENDIAN)
- goto no_packing_needed;
- for (i = 0; i < count; i++) {
- unsigned len = fixed64_pack(((uint64_t *) array)[i], scratch);
- buffer->append(buffer, len, scratch);
- case PROTOBUF_C_TYPE_INT32:
- for (i = 0; i < count; i++) {
- unsigned len = int32_pack(((int32_t *) array)[i], scratch);
- buffer->append(buffer, len, scratch);
- case PROTOBUF_C_TYPE_SINT32:
- for (i = 0; i < count; i++) {
- unsigned len = sint32_pack(((int32_t *) array)[i], scratch);
- buffer->append(buffer, len, scratch);
- case PROTOBUF_C_TYPE_ENUM:
- case PROTOBUF_C_TYPE_UINT32:
- for (i = 0; i < count; i++) {
- unsigned len = uint32_pack(((uint32_t *) array)[i], scratch);
- buffer->append(buffer, len, scratch);
- case PROTOBUF_C_TYPE_SINT64:
- for (i = 0; i < count; i++) {
- unsigned len = sint64_pack(((int64_t *) array)[i], scratch);
- buffer->append(buffer, len, scratch);
- case PROTOBUF_C_TYPE_INT64:
- case PROTOBUF_C_TYPE_UINT64:
- for (i = 0; i < count; i++) {
- unsigned len = uint64_pack(((uint64_t *) array)[i], scratch);
- buffer->append(buffer, len, scratch);
- case PROTOBUF_C_TYPE_BOOL:
- for (i = 0; i < count; i++) {
- unsigned len = boolean_pack(((protobuf_c_boolean *) array)[i], scratch);
- buffer->append(buffer, len, scratch);
- PROTOBUF_C__ASSERT_NOT_REACHED();
-#if !defined(WORDS_BIGENDIAN)
- buffer->append(buffer, rv, array);
-repeated_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
- unsigned count, const void *member,
- ProtobufCBuffer *buffer)
- char *array = *(char * const *) member;
- if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) {
- uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2];
- size_t rv = tag_pack(field->id, scratch);
- size_t payload_len = get_packed_payload_length(field, count, array);
- scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
- rv += uint32_pack(payload_len, scratch + rv);
- buffer->append(buffer, rv, scratch);
- tmp = pack_buffer_packed_payload(field, count, array, buffer);
- assert(tmp == payload_len);
- return rv + payload_len;
- /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */
- siz = sizeof_elt_in_repeated_array(field->type);
- for (i = 0; i < count; i++) {
- rv += required_field_pack_to_buffer(field, array, buffer);
- array = ((char*)array) + siz;
-unknown_field_pack_to_buffer(const ProtobufCMessageUnknownField *field,
- ProtobufCBuffer *buffer)
- uint8_t header[MAX_UINT64_ENCODED_SIZE];
- size_t rv = tag_pack(field->tag, header);
- header[0] |= field->wire_type;
- buffer->append(buffer, rv, header);
- buffer->append(buffer, field->len, field->data);
- return rv + field->len;
-protobuf_c_message_pack_to_buffer(const ProtobufCMessage *message,
- ProtobufCBuffer *buffer)
- ASSERT_IS_MESSAGE(message);
- for (i = 0; i < message->descriptor->n_fields; i++) {
- const ProtobufCFieldDescriptor *field =
- message->descriptor->fields + i;
- ((const char *) message) + field->offset;
- ((const char *) message) + field->quantifier_offset;
- if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
- rv += required_field_pack_to_buffer(field, member, buffer);
- } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) {
- rv += optional_field_pack_to_buffer(
- rv += repeated_field_pack_to_buffer(
- *(const size_t *) qmember,
- for (i = 0; i < message->n_unknown_fields; i++)
- rv += unknown_field_pack_to_buffer(&message->unknown_fields[i], buffer);
- * \defgroup unpack unpacking implementation
- * Routines mainly used by the unpacking functions.
-int_range_lookup(unsigned n_ranges, const ProtobufCIntRange *ranges, int value)
- unsigned mid = start + n / 2;
- if (value < ranges[mid].start_value) {
- } else if (value >= ranges[mid].start_value +
- (int) (ranges[mid + 1].orig_index -
- ranges[mid].orig_index))
- unsigned new_start = mid + 1;
- n = start + n - new_start;
- return (value - ranges[mid].start_value) +
- ranges[mid].orig_index;
- unsigned start_orig_index = ranges[start].orig_index;
- ranges[start + 1].orig_index - start_orig_index;
- if (ranges[start].start_value <= value &&
- value < (int) (ranges[start].start_value + range_size))
- return (value - ranges[start].start_value) +
-parse_tag_and_wiretype(size_t len,
- ProtobufCWireType *wiretype_out)
- unsigned max_rv = len > 5 ? 5 : len;
- uint32_t tag = (data[0] & 0x7f) >> 3;
- *wiretype_out = data[0] & 7;
- if ((data[0] & 0x80) == 0) {
- for (rv = 1; rv < max_rv; rv++) {
- tag |= (data[rv] & 0x7f) << shift;
- tag |= data[rv] << shift;
- return 0; /* error: bad header */
-/* sizeof(ScannedMember) must be <= (1<<BOUND_SIZEOF_SCANNED_MEMBER_LOG2) */
-#define BOUND_SIZEOF_SCANNED_MEMBER_LOG2 5
-typedef struct _ScannedMember ScannedMember;
-/** Field as it's being read. */
- uint32_t tag; /**< Field tag. */
- uint8_t wire_type; /**< Field type. */
- uint8_t length_prefix_len; /**< Prefix length. */
- const ProtobufCFieldDescriptor *field; /**< Field descriptor. */
- size_t len; /**< Field length. */
- const uint8_t *data; /**< Pointer to field data. */
-scan_length_prefixed_data(size_t len, const uint8_t *data,
- size_t *prefix_len_out)
- unsigned hdr_max = len < 5 ? len : 5;
- for (i = 0; i < hdr_max; i++) {
- val |= (data[i] & 0x7f) << shift;
- if ((data[i] & 0x80) == 0)
- PROTOBUF_C_UNPACK_ERROR("error parsing length for length-prefixed data");
- *prefix_len_out = hdr_len;
- if (hdr_len + val > len) {
- PROTOBUF_C_UNPACK_ERROR("data too short after length-prefix of %u", val);
-max_b128_numbers(size_t len, const uint8_t *data)
- if ((*data++ & 0x80) == 0)
- * Merge earlier message into a latter message.
- * For numeric types and strings, if the same value appears multiple
- * times, the parser accepts the last value it sees. For embedded
- * message fields, the parser merges multiple instances of the same
- * field. That is, all singular scalar fields in the latter instance
- * replace those in the former, singular embedded messages are merged,
- * and repeated fields are concatenated.
- * The earlier message should be freed after calling this function, as
- * some of its fields may have been reused and changed to their default
- * values during the merge.
-static protobuf_c_boolean
-merge_messages(ProtobufCMessage *earlier_msg,
- ProtobufCMessage *latter_msg,
- ProtobufCAllocator *allocator)
- const ProtobufCFieldDescriptor *fields =
- earlier_msg->descriptor->fields;
- for (i = 0; i < latter_msg->descriptor->n_fields; i++) {
- if (fields[i].label == PROTOBUF_C_LABEL_REPEATED) {
- STRUCT_MEMBER_PTR(size_t, earlier_msg,
- fields[i].quantifier_offset);
- STRUCT_MEMBER_PTR(uint8_t *, earlier_msg,
- STRUCT_MEMBER_PTR(size_t, latter_msg,
- fields[i].quantifier_offset);
- STRUCT_MEMBER_PTR(uint8_t *, latter_msg,
- /* Concatenate the repeated field */
- sizeof_elt_in_repeated_array(fields[i].type);
- new_field = do_alloc(allocator,
- (*n_earlier + *n_latter) * el_size);
- memcpy(new_field, *p_earlier,
- do_free(allocator, *p_latter);
- do_free(allocator, *p_earlier);
- *n_latter = *n_earlier + *n_latter;
- /* Zero copy the repeated field from the earlier message */
- *n_latter = *n_earlier;
- *p_latter = *p_earlier;
- /* Make sure the field does not get double freed */
- } else if (fields[i].type == PROTOBUF_C_TYPE_MESSAGE) {
- ProtobufCMessage **em =
- STRUCT_MEMBER_PTR(ProtobufCMessage *,
- ProtobufCMessage **lm =
- STRUCT_MEMBER_PTR(ProtobufCMessage *,
- /* Zero copy the optional message */
- assert(fields[i].label ==
- PROTOBUF_C_LABEL_OPTIONAL);
- } else if (fields[i].label == PROTOBUF_C_LABEL_OPTIONAL) {
- protobuf_c_boolean need_to_merge = FALSE;
- STRUCT_MEMBER_P(earlier_msg, fields[i].offset);
- STRUCT_MEMBER_P(latter_msg, fields[i].offset);
- const void *def_val = fields[i].default_value;
- switch (fields[i].type) {
- case PROTOBUF_C_TYPE_BYTES: {
- ((ProtobufCBinaryData *) earlier_elem)->data;
- ((ProtobufCBinaryData *) latter_elem)->data;
- const ProtobufCBinaryData *d_bd =
- (ProtobufCBinaryData *) def_val;
- el_size = sizeof(ProtobufCBinaryData);
- e_data != d_bd->data)) &&
- l_data == d_bd->data));
- case PROTOBUF_C_TYPE_STRING: {
- char *e_str = *(char **) earlier_elem;
- char *l_str = *(char **) latter_elem;
- const char *d_str = def_val;
- el_size = sizeof(char *);
- need_to_merge = e_str != d_str && l_str == d_str;
- el_size = sizeof_elt_in_repeated_array(fields[i].type);
- STRUCT_MEMBER(protobuf_c_boolean,
- fields[i].quantifier_offset) &&
- !STRUCT_MEMBER(protobuf_c_boolean,
- fields[i].quantifier_offset);
- memcpy(latter_elem, earlier_elem, el_size);
- * Reset the element from the old message to 0
- * to make sure earlier message deallocation
- * doesn't corrupt zero-copied data in the new
- * message, earlier message will be freed after
- * this function is called anyway
- memset(earlier_elem, 0, el_size);
- if (fields[i].quantifier_offset != 0) {
- /* Set the has field, if applicable */
- STRUCT_MEMBER(protobuf_c_boolean,
- quantifier_offset) = TRUE;
- STRUCT_MEMBER(protobuf_c_boolean,
- quantifier_offset) = FALSE;
- * Count packed elements.
- * Given a raw slab of packed-repeated values, determine the number of
- * elements. This function detects certain kinds of errors but not
- * others; the remaining error checking is done by
- * parse_packed_repeated_member().
-static protobuf_c_boolean
-count_packed_elements(ProtobufCType type,
- size_t len, const uint8_t *data, size_t *count_out)
- case PROTOBUF_C_TYPE_SFIXED32:
- case PROTOBUF_C_TYPE_FIXED32:
- case PROTOBUF_C_TYPE_FLOAT:
- PROTOBUF_C_UNPACK_ERROR("length must be a multiple of 4 for fixed-length 32-bit types");
- case PROTOBUF_C_TYPE_SFIXED64:
- case PROTOBUF_C_TYPE_FIXED64:
- case PROTOBUF_C_TYPE_DOUBLE:
- PROTOBUF_C_UNPACK_ERROR("length must be a multiple of 8 for fixed-length 64-bit types");
- case PROTOBUF_C_TYPE_INT32:
- case PROTOBUF_C_TYPE_SINT32:
- case PROTOBUF_C_TYPE_ENUM:
- case PROTOBUF_C_TYPE_UINT32:
- case PROTOBUF_C_TYPE_INT64:
- case PROTOBUF_C_TYPE_SINT64:
- case PROTOBUF_C_TYPE_UINT64:
- *count_out = max_b128_numbers(len, data);
- case PROTOBUF_C_TYPE_BOOL:
- case PROTOBUF_C_TYPE_STRING:
- case PROTOBUF_C_TYPE_BYTES:
- case PROTOBUF_C_TYPE_MESSAGE:
- PROTOBUF_C_UNPACK_ERROR("bad protobuf-c type %u for packed-repeated", type);
-parse_uint32(unsigned len, const uint8_t *data)
- uint32_t rv = data[0] & 0x7f;
- rv |= ((uint32_t) (data[1] & 0x7f) << 7);
- rv |= ((uint32_t) (data[2] & 0x7f) << 14);
- rv |= ((uint32_t) (data[3] & 0x7f) << 21);
- rv |= ((uint32_t) (data[4]) << 28);
-parse_int32(unsigned len, const uint8_t *data)
- return parse_uint32(len, data);
-parse_fixed_uint32(const uint8_t *data)
-#if !defined(WORDS_BIGENDIAN)
- ((uint32_t) (data[1]) << 8) |
- ((uint32_t) (data[2]) << 16) |
- ((uint32_t) (data[3]) << 24);
-parse_uint64(unsigned len, const uint8_t *data)
- return parse_uint32(len, data);
- rv = ((uint64_t) (data[0] & 0x7f)) |
- ((uint64_t) (data[1] & 0x7f) << 7) |
- ((uint64_t) (data[2] & 0x7f) << 14) |
- ((uint64_t) (data[3] & 0x7f) << 21);
- for (i = 4; i < len; i++) {
- rv |= (((uint64_t) (data[i] & 0x7f)) << shift);
-parse_fixed_uint64(const uint8_t *data)
-#if !defined(WORDS_BIGENDIAN)
- return (uint64_t) parse_fixed_uint32(data) |
- (((uint64_t) parse_fixed_uint32(data + 4)) << 32);
-static protobuf_c_boolean
-parse_boolean(unsigned len, const uint8_t *data)
- for (i = 0; i < len; i++)
-static protobuf_c_boolean
-parse_required_member(ScannedMember *scanned_member,
- ProtobufCAllocator *allocator,
- protobuf_c_boolean maybe_clear)
- unsigned len = scanned_member->len;
- const uint8_t *data = scanned_member->data;
- ProtobufCWireType wire_type = scanned_member->wire_type;
- switch (scanned_member->field->type) {
- case PROTOBUF_C_TYPE_INT32:
- if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
- *(uint32_t *) member = parse_int32(len, data);
- case PROTOBUF_C_TYPE_UINT32:
- if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
- *(uint32_t *) member = parse_uint32(len, data);
- case PROTOBUF_C_TYPE_SINT32:
- if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
- *(int32_t *) member = unzigzag32(parse_uint32(len, data));
- case PROTOBUF_C_TYPE_SFIXED32:
- case PROTOBUF_C_TYPE_FIXED32:
- case PROTOBUF_C_TYPE_FLOAT:
- if (wire_type != PROTOBUF_C_WIRE_TYPE_32BIT)
- *(uint32_t *) member = parse_fixed_uint32(data);
- case PROTOBUF_C_TYPE_INT64:
- case PROTOBUF_C_TYPE_UINT64:
- if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
- *(uint64_t *) member = parse_uint64(len, data);
- case PROTOBUF_C_TYPE_SINT64:
- if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
- *(int64_t *) member = unzigzag64(parse_uint64(len, data));
- case PROTOBUF_C_TYPE_SFIXED64:
- case PROTOBUF_C_TYPE_FIXED64:
- case PROTOBUF_C_TYPE_DOUBLE:
- if (wire_type != PROTOBUF_C_WIRE_TYPE_64BIT)
- *(uint64_t *) member = parse_fixed_uint64(data);
- case PROTOBUF_C_TYPE_BOOL:
- *(protobuf_c_boolean *) member = parse_boolean(len, data);
- case PROTOBUF_C_TYPE_ENUM:
- if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
- *(uint32_t *) member = parse_uint32(len, data);
- case PROTOBUF_C_TYPE_STRING: {
- unsigned pref_len = scanned_member->length_prefix_len;
- if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
- if (maybe_clear && *pstr != NULL) {
- const char *def = scanned_member->field->default_value;
- if (*pstr != NULL && *pstr != def)
- do_free(allocator, *pstr);
- *pstr = do_alloc(allocator, len - pref_len + 1);
- memcpy(*pstr, data + pref_len, len - pref_len);
- (*pstr)[len - pref_len] = 0;
- case PROTOBUF_C_TYPE_BYTES: {
- ProtobufCBinaryData *bd = member;
- const ProtobufCBinaryData *def_bd;
- unsigned pref_len = scanned_member->length_prefix_len;
- if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
- def_bd = scanned_member->field->default_value;
- (def_bd == NULL || bd->data != def_bd->data))
- do_free(allocator, bd->data);
- if (len - pref_len > 0) {
- bd->data = do_alloc(allocator, len - pref_len);
- memcpy(bd->data, data + pref_len, len - pref_len);
- bd->len = len - pref_len;
- case PROTOBUF_C_TYPE_MESSAGE: {
- ProtobufCMessage **pmessage = member;
- ProtobufCMessage *subm;
- const ProtobufCMessage *def_mess;
- protobuf_c_boolean merge_successful = TRUE;
- unsigned pref_len = scanned_member->length_prefix_len;
- if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
- def_mess = scanned_member->field->default_value;
- subm = protobuf_c_message_unpack(scanned_member->field->descriptor,
- merge_successful = merge_messages(*pmessage, subm, allocator);
- /* Delete the previous message */
- protobuf_c_message_free_unpacked(*pmessage, allocator);
- if (subm == NULL || !merge_successful)
-static protobuf_c_boolean
-parse_optional_member(ScannedMember *scanned_member,
- ProtobufCMessage *message,
- ProtobufCAllocator *allocator)
- if (!parse_required_member(scanned_member, member, allocator, TRUE))
- if (scanned_member->field->quantifier_offset != 0)
- STRUCT_MEMBER(protobuf_c_boolean,
- scanned_member->field->quantifier_offset) = TRUE;
-static protobuf_c_boolean
-parse_repeated_member(ScannedMember *scanned_member,
- ProtobufCMessage *message,
- ProtobufCAllocator *allocator)
- const ProtobufCFieldDescriptor *field = scanned_member->field;
- size_t *p_n = STRUCT_MEMBER_PTR(size_t, message, field->quantifier_offset);
- size_t siz = sizeof_elt_in_repeated_array(field->type);
- char *array = *(char **) member;
- if (!parse_required_member(scanned_member, array + siz * (*p_n),
-scan_varint(unsigned len, const uint8_t *data)
- for (i = 0; i < len; i++)
- if ((data[i] & 0x80) == 0)
-static protobuf_c_boolean
-parse_packed_repeated_member(ScannedMember *scanned_member,
- ProtobufCMessage *message)
- const ProtobufCFieldDescriptor *field = scanned_member->field;
- size_t *p_n = STRUCT_MEMBER_PTR(size_t, message, field->quantifier_offset);
- size_t siz = sizeof_elt_in_repeated_array(field->type);
- void *array = *(char **) member + siz * (*p_n);
- const uint8_t *at = scanned_member->data + scanned_member->length_prefix_len;
- size_t rem = scanned_member->len - scanned_member->length_prefix_len;
- case PROTOBUF_C_TYPE_SFIXED32:
- case PROTOBUF_C_TYPE_FIXED32:
- case PROTOBUF_C_TYPE_FLOAT:
- count = (scanned_member->len - scanned_member->length_prefix_len) / 4;
-#if !defined(WORDS_BIGENDIAN)
- goto no_unpacking_needed;
- for (i = 0; i < count; i++) {
- ((uint32_t *) array)[i] = parse_fixed_uint32(at);
- case PROTOBUF_C_TYPE_SFIXED64:
- case PROTOBUF_C_TYPE_FIXED64:
- case PROTOBUF_C_TYPE_DOUBLE:
- count = (scanned_member->len - scanned_member->length_prefix_len) / 8;
-#if !defined(WORDS_BIGENDIAN)
- goto no_unpacking_needed;
- for (i = 0; i < count; i++) {
- ((uint64_t *) array)[i] = parse_fixed_uint64(at);
- case PROTOBUF_C_TYPE_INT32:
- unsigned s = scan_varint(rem, at);
- PROTOBUF_C_UNPACK_ERROR("bad packed-repeated int32 value");
- ((int32_t *) array)[count++] = parse_int32(s, at);
- case PROTOBUF_C_TYPE_SINT32:
- unsigned s = scan_varint(rem, at);
- PROTOBUF_C_UNPACK_ERROR("bad packed-repeated sint32 value");
- ((int32_t *) array)[count++] = unzigzag32(parse_uint32(s, at));
- case PROTOBUF_C_TYPE_ENUM:
- case PROTOBUF_C_TYPE_UINT32:
- unsigned s = scan_varint(rem, at);
- PROTOBUF_C_UNPACK_ERROR("bad packed-repeated enum or uint32 value");
- ((uint32_t *) array)[count++] = parse_uint32(s, at);
- case PROTOBUF_C_TYPE_SINT64:
- unsigned s = scan_varint(rem, at);
- PROTOBUF_C_UNPACK_ERROR("bad packed-repeated sint64 value");
- ((int64_t *) array)[count++] = unzigzag64(parse_uint64(s, at));
- case PROTOBUF_C_TYPE_INT64:
- case PROTOBUF_C_TYPE_UINT64:
- unsigned s = scan_varint(rem, at);
- PROTOBUF_C_UNPACK_ERROR("bad packed-repeated int64/uint64 value");
- ((int64_t *) array)[count++] = parse_uint64(s, at);
- case PROTOBUF_C_TYPE_BOOL:
- for (i = 0; i < count; i++) {
- PROTOBUF_C_UNPACK_ERROR("bad packed-repeated boolean value");
- ((protobuf_c_boolean *) array)[i] = at[i];
- PROTOBUF_C__ASSERT_NOT_REACHED();
-#if !defined(WORDS_BIGENDIAN)
- memcpy(array, at, count * siz);
-static protobuf_c_boolean
-is_packable_type(ProtobufCType type)
- type != PROTOBUF_C_TYPE_STRING &&
- type != PROTOBUF_C_TYPE_BYTES &&
- type != PROTOBUF_C_TYPE_MESSAGE;
-static protobuf_c_boolean
-parse_member(ScannedMember *scanned_member,
- ProtobufCMessage *message,
- ProtobufCAllocator *allocator)
- const ProtobufCFieldDescriptor *field = scanned_member->field;
- ProtobufCMessageUnknownField *ufield =
- message->unknown_fields +
- (message->n_unknown_fields++);
- ufield->tag = scanned_member->tag;
- ufield->wire_type = scanned_member->wire_type;
- ufield->len = scanned_member->len;
- ufield->data = do_alloc(allocator, scanned_member->len);
- if (ufield->data == NULL)
- memcpy(ufield->data, scanned_member->data, ufield->len);
- member = (char *) message + field->offset;
- switch (field->label) {
- case PROTOBUF_C_LABEL_REQUIRED:
- return parse_required_member(scanned_member, member,
- case PROTOBUF_C_LABEL_OPTIONAL:
- return parse_optional_member(scanned_member, member,
- case PROTOBUF_C_LABEL_REPEATED:
- if (scanned_member->wire_type ==
- PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED &&
- (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED) ||
- is_packable_type(field->type)))
- return parse_packed_repeated_member(scanned_member,
- return parse_repeated_member(scanned_member,
- PROTOBUF_C__ASSERT_NOT_REACHED();
- * Initialise messages generated by old code.
- * This function is used if desc->message_init == NULL (which occurs
- * for old code, and which would be useful to support allocating
- * descriptors dynamically).
-message_init_generic(const ProtobufCMessageDescriptor *desc,
- ProtobufCMessage *message)
- memset(message, 0, desc->sizeof_message);
- message->descriptor = desc;
- for (i = 0; i < desc->n_fields; i++) {
- if (desc->fields[i].default_value != NULL &&
- desc->fields[i].label != PROTOBUF_C_LABEL_REPEATED)
- STRUCT_MEMBER_P(message, desc->fields[i].offset);
- const void *dv = desc->fields[i].default_value;
- switch (desc->fields[i].type) {
- case PROTOBUF_C_TYPE_INT32:
- case PROTOBUF_C_TYPE_SINT32:
- case PROTOBUF_C_TYPE_SFIXED32:
- case PROTOBUF_C_TYPE_UINT32:
- case PROTOBUF_C_TYPE_FIXED32:
- case PROTOBUF_C_TYPE_FLOAT:
- case PROTOBUF_C_TYPE_ENUM:
- case PROTOBUF_C_TYPE_INT64:
- case PROTOBUF_C_TYPE_SINT64:
- case PROTOBUF_C_TYPE_SFIXED64:
- case PROTOBUF_C_TYPE_UINT64:
- case PROTOBUF_C_TYPE_FIXED64:
- case PROTOBUF_C_TYPE_DOUBLE:
- case PROTOBUF_C_TYPE_BOOL:
- memcpy(field, dv, sizeof(protobuf_c_boolean));
- case PROTOBUF_C_TYPE_BYTES:
- memcpy(field, dv, sizeof(ProtobufCBinaryData));
- case PROTOBUF_C_TYPE_STRING:
- case PROTOBUF_C_TYPE_MESSAGE:
- * The next line essentially implements a cast
- * from const, which is totally unavoidable.
- *(const void **) field = dv;
- * ScannedMember slabs (an unpacking implementation detail). Before doing real
- * unpacking, we first scan through the elements to see how many there are (for
- * repeated fields), and which field to use (for non-repeated fields given
- * In order to avoid allocations for small messages, we keep a stack-allocated
- * slab of ScannedMembers of size FIRST_SCANNED_MEMBER_SLAB_SIZE (16). After we
- * fill that up, we allocate each slab twice as large as the previous one.
-#define FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2 4
- * The number of slabs, including the stack-allocated ones; choose the number so
- * that we would overflow if we needed a slab larger than provided.
-#define MAX_SCANNED_MEMBER_SLAB \
- (sizeof(unsigned int)*8 - 1 \
- - BOUND_SIZEOF_SCANNED_MEMBER_LOG2 \
- - FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2)
-#define REQUIRED_FIELD_BITMAP_SET(index) \
- (required_fields_bitmap[(index)/8] |= (1<<((index)%8)))
-#define REQUIRED_FIELD_BITMAP_IS_SET(index) \
- (required_fields_bitmap[(index)/8] & (1<<((index)%8)))
-protobuf_c_message_unpack(const ProtobufCMessageDescriptor *desc,
- ProtobufCAllocator *allocator,
- size_t len, const uint8_t *data)
- const uint8_t *at = data;
- const ProtobufCFieldDescriptor *last_field = desc->fields + 0;
- ScannedMember first_member_slab[1 <<
- FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2];
- * scanned_member_slabs[i] is an array of arrays of ScannedMember.
- * The first slab (scanned_member_slabs[0] is just a pointer to
- * first_member_slab), above. All subsequent slabs will be allocated
- ScannedMember *scanned_member_slabs[MAX_SCANNED_MEMBER_SLAB + 1];
- unsigned which_slab = 0; /* the slab we are currently populating */
- unsigned in_slab_index = 0; /* number of members in the slab */
- unsigned last_field_index = 0;
- unsigned required_fields_bitmap_len;
- unsigned char required_fields_bitmap_stack[16];
- unsigned char *required_fields_bitmap = required_fields_bitmap_stack;
- protobuf_c_boolean required_fields_bitmap_alloced = FALSE;
- ASSERT_IS_MESSAGE_DESCRIPTOR(desc);
- allocator = &protobuf_c__allocator;
- rv = do_alloc(allocator, desc->sizeof_message);
- scanned_member_slabs[0] = first_member_slab;
- required_fields_bitmap_len = (desc->n_fields + 7) / 8;
- if (required_fields_bitmap_len > sizeof(required_fields_bitmap_stack)) {
- required_fields_bitmap = do_alloc(allocator, required_fields_bitmap_len);
- if (!required_fields_bitmap) {
- do_free(allocator, rv);
- required_fields_bitmap_alloced = TRUE;
- memset(required_fields_bitmap, 0, required_fields_bitmap_len);
- * Generated code always defines "message_init". However, we provide a
- * fallback for (1) users of old protobuf-c generated-code that do not
- * provide the function, and (2) descriptors constructed from some other
- * source (most likely, direct construction from the .proto file).
- if (desc->message_init != NULL)
- protobuf_c_message_init(desc, rv);
- message_init_generic(desc, rv);
- ProtobufCWireType wire_type;
- size_t used = parse_tag_and_wiretype(rem, at, &tag, &wire_type);
- const ProtobufCFieldDescriptor *field;
- memset(&tmp, 0, sizeof(ScannedMember));
- PROTOBUF_C_UNPACK_ERROR("error parsing tag/wiretype at offset %u",
- (unsigned) (at - data));
- goto error_cleanup_during_scan;
- * \todo Consider optimizing for field[1].id == tag, if field[1]
- if (last_field == NULL || last_field->id != tag) {
- int_range_lookup(desc->n_field_ranges,
- field = desc->fields + field_index;
- last_field_index = field_index;
- if (field != NULL && field->label == PROTOBUF_C_LABEL_REQUIRED)
- REQUIRED_FIELD_BITMAP_SET(last_field_index);
- tmp.wire_type = wire_type;
- tmp.length_prefix_len = 0;
- case PROTOBUF_C_WIRE_TYPE_VARINT: {
- unsigned max_len = rem < 10 ? rem : 10;
- for (i = 0; i < max_len; i++)
- if ((at[i] & 0x80) == 0)
- PROTOBUF_C_UNPACK_ERROR("unterminated varint at offset %u",
- (unsigned) (at - data));
- goto error_cleanup_during_scan;
- case PROTOBUF_C_WIRE_TYPE_64BIT:
- PROTOBUF_C_UNPACK_ERROR("too short after 64bit wiretype at offset %u",
- (unsigned) (at - data));
- goto error_cleanup_during_scan;
- case PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED: {
- tmp.len = scan_length_prefixed_data(rem, at, &pref_len);
- /* NOTE: scan_length_prefixed_data calls UNPACK_ERROR */
- goto error_cleanup_during_scan;
- tmp.length_prefix_len = pref_len;
- case PROTOBUF_C_WIRE_TYPE_32BIT:
- PROTOBUF_C_UNPACK_ERROR("too short after 32bit wiretype at offset %u",
- (unsigned) (at - data));
- goto error_cleanup_during_scan;
- PROTOBUF_C_UNPACK_ERROR("unsupported tag %u at offset %u",
- wire_type, (unsigned) (at - data));
- goto error_cleanup_during_scan;
- if (in_slab_index == (1U <<
- (which_slab + FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2)))
- if (which_slab == MAX_SCANNED_MEMBER_SLAB) {
- PROTOBUF_C_UNPACK_ERROR("too many fields");
- goto error_cleanup_during_scan;
- size = sizeof(ScannedMember)
- << (which_slab + FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2);
- scanned_member_slabs[which_slab] = do_alloc(allocator, size);
- if (scanned_member_slabs[which_slab] == NULL)
- goto error_cleanup_during_scan;
- scanned_member_slabs[which_slab][in_slab_index++] = tmp;
- if (field != NULL && field->label == PROTOBUF_C_LABEL_REPEATED) {
- size_t *n = STRUCT_MEMBER_PTR(size_t, rv,
- field->quantifier_offset);
- if (wire_type == PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED &&
- (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED) ||
- is_packable_type(field->type)))
- if (!count_packed_elements(field->type,
- PROTOBUF_C_UNPACK_ERROR("counting packed elements");
- goto error_cleanup_during_scan;
- /* allocate space for repeated fields, also check that all required fields have been set */
- for (f = 0; f < desc->n_fields; f++) {
- const ProtobufCFieldDescriptor *field = desc->fields + f;
- if (field->label == PROTOBUF_C_LABEL_REPEATED) {
- sizeof_elt_in_repeated_array(field->type);
- STRUCT_MEMBER_PTR(size_t, rv,
- field->quantifier_offset);
- assert(rv->descriptor != NULL);
-#define CLEAR_REMAINING_N_PTRS() \
- for(f++;f < desc->n_fields; f++) \
- field = desc->fields + f; \
- if (field->label == PROTOBUF_C_LABEL_REPEATED) \
- STRUCT_MEMBER (size_t, rv, field->quantifier_offset) = 0; \
- a = do_alloc(allocator, siz * n);
- CLEAR_REMAINING_N_PTRS();
- STRUCT_MEMBER(void *, rv, field->offset) = a;
- } else if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
- if (field->default_value == NULL &&
- !REQUIRED_FIELD_BITMAP_IS_SET(f))
- CLEAR_REMAINING_N_PTRS();
- PROTOBUF_C_UNPACK_ERROR("message '%s': missing required field '%s'",
- desc->name, field->name);
-#undef CLEAR_REMAINING_N_PTRS
- /* allocate space for unknown fields */
- rv->unknown_fields = do_alloc(allocator,
- n_unknown * sizeof(ProtobufCMessageUnknownField));
- if (rv->unknown_fields == NULL)
- for (i_slab = 0; i_slab <= which_slab; i_slab++) {
- unsigned max = (i_slab == which_slab) ?
- in_slab_index : (1U << (i_slab + 4));
- ScannedMember *slab = scanned_member_slabs[i_slab];
- for (j = 0; j < max; j++) {
- if (!parse_member(slab + j, rv, allocator)) {
- PROTOBUF_C_UNPACK_ERROR("error parsing member %s of %s",
- slab->field ? slab->field->name : "*unknown-field*",
- for (j = 1; j <= which_slab; j++)
- do_free(allocator, scanned_member_slabs[j]);
- if (required_fields_bitmap_alloced)
- do_free(allocator, required_fields_bitmap);
- protobuf_c_message_free_unpacked(rv, allocator);
- for (j = 1; j <= which_slab; j++)
- do_free(allocator, scanned_member_slabs[j]);
- if (required_fields_bitmap_alloced)
- do_free(allocator, required_fields_bitmap);
-error_cleanup_during_scan:
- do_free(allocator, rv);
- for (j = 1; j <= which_slab; j++)
- do_free(allocator, scanned_member_slabs[j]);
- if (required_fields_bitmap_alloced)
- do_free(allocator, required_fields_bitmap);
-protobuf_c_message_free_unpacked(ProtobufCMessage *message,
- ProtobufCAllocator *allocator)
- const ProtobufCMessageDescriptor *desc = message->descriptor;
- ASSERT_IS_MESSAGE(message);
- allocator = &protobuf_c__allocator;
- message->descriptor = NULL;
- for (f = 0; f < desc->n_fields; f++) {
- if (desc->fields[f].label == PROTOBUF_C_LABEL_REPEATED) {
- size_t n = STRUCT_MEMBER(size_t,
- desc->fields[f].quantifier_offset);
- void *arr = STRUCT_MEMBER(void *,
- desc->fields[f].offset);
- if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING) {
- for (i = 0; i < n; i++)
- do_free(allocator, ((char **) arr)[i]);
- } else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES) {
- for (i = 0; i < n; i++)
- do_free(allocator, ((ProtobufCBinaryData *) arr)[i].data);
- } else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE) {
- for (i = 0; i < n; i++)
- protobuf_c_message_free_unpacked(
- ((ProtobufCMessage **) arr)[i],
- do_free(allocator, arr);
- } else if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING) {
- char *str = STRUCT_MEMBER(char *, message,
- desc->fields[f].offset);
- if (str && str != desc->fields[f].default_value)
- do_free(allocator, str);
- } else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES) {
- void *data = STRUCT_MEMBER(ProtobufCBinaryData, message,
- desc->fields[f].offset).data;
- const ProtobufCBinaryData *default_bd;
- default_bd = desc->fields[f].default_value;
- default_bd->data != data))
- do_free(allocator, data);
- } else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE) {
- sm = STRUCT_MEMBER(ProtobufCMessage *, message,
- desc->fields[f].offset);
- if (sm && sm != desc->fields[f].default_value)
- protobuf_c_message_free_unpacked(sm, allocator);
- for (f = 0; f < message->n_unknown_fields; f++)
- do_free(allocator, message->unknown_fields[f].data);
- if (message->unknown_fields != NULL)
- do_free(allocator, message->unknown_fields);
- do_free(allocator, message);
-protobuf_c_message_init(const ProtobufCMessageDescriptor * descriptor,
- descriptor->message_init((ProtobufCMessage *) (message));
-protobuf_c_message_check(const ProtobufCMessage *message)
- !message->descriptor ||
- message->descriptor->magic != PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC)
- for (i = 0; i < message->descriptor->n_fields; i++) {
- const ProtobufCFieldDescriptor *f = message->descriptor->fields + i;
- ProtobufCType type = f->type;
- ProtobufCLabel label = f->label;
- void *field = STRUCT_MEMBER_P (message, f->offset);
- if (label == PROTOBUF_C_LABEL_REPEATED) {
- size_t *quantity = STRUCT_MEMBER_P (message, f->quantifier_offset);
- if (*quantity > 0 && *(void **) field == NULL) {
- if (type == PROTOBUF_C_TYPE_MESSAGE) {
- ProtobufCMessage **submessage = *(ProtobufCMessage ***) field;
- for (j = 0; j < *quantity; j++) {
- if (!protobuf_c_message_check(submessage[j]))
- } else if (type == PROTOBUF_C_TYPE_STRING) {
- char **string = *(char ***) field;
- for (j = 0; j < *quantity; j++) {
- } else if (type == PROTOBUF_C_TYPE_BYTES) {
- ProtobufCBinaryData *bd = *(ProtobufCBinaryData **) field;
- for (j = 0; j < *quantity; j++) {
- if (bd[j].len > 0 && bd[j].data == NULL)
- } else { /* PROTOBUF_C_LABEL_REQUIRED or PROTOBUF_C_LABEL_OPTIONAL */
- if (type == PROTOBUF_C_TYPE_MESSAGE) {
- ProtobufCMessage *submessage = *(ProtobufCMessage **) field;
- if (label == PROTOBUF_C_LABEL_REQUIRED || submessage != NULL) {
- if (!protobuf_c_message_check(submessage))
- } else if (type == PROTOBUF_C_TYPE_STRING) {
- char *string = *(char **) field;
- if (label == PROTOBUF_C_LABEL_REQUIRED && string == NULL)
- } else if (type == PROTOBUF_C_TYPE_BYTES) {
- protobuf_c_boolean *has = STRUCT_MEMBER_P (message, f->quantifier_offset);
- ProtobufCBinaryData *bd = field;
- if (label == PROTOBUF_C_LABEL_REQUIRED || *has == TRUE) {
- if (bd->len > 0 && bd->data == NULL)
-typedef void (*GenericHandler) (void *service,
- const ProtobufCMessage *input,
- ProtobufCClosure closure,
-protobuf_c_service_invoke_internal(ProtobufCService *service,
- const ProtobufCMessage *input,
- ProtobufCClosure closure,
- GenericHandler *handlers;
- GenericHandler handler;
- * Verify that method_index is within range. If this fails, you are
- * likely invoking a newly added method on an old service. (Although
- * other memory corruption bugs can cause this assertion too.)
- assert(method_index < service->descriptor->n_methods);
- * Get the array of virtual methods (which are enumerated by the
- handlers = (GenericHandler *) (service + 1);
- * Get our method and invoke it.
- * \todo Seems like handler == NULL is a situation that needs handling.
- handler = handlers[method_index];
- (*handler)(service, input, closure, closure_data);
-protobuf_c_service_generated_init(ProtobufCService *service,
- const ProtobufCServiceDescriptor *descriptor,
- ProtobufCServiceDestroy destroy)
- ASSERT_IS_SERVICE_DESCRIPTOR(descriptor);
- service->descriptor = descriptor;
- service->destroy = destroy;
- service->invoke = protobuf_c_service_invoke_internal;
- memset(service + 1, 0, descriptor->n_methods * sizeof(GenericHandler));
-void protobuf_c_service_destroy(ProtobufCService *service)
- service->destroy(service);
-/* --- querying the descriptors --- */
-const ProtobufCEnumValue *
-protobuf_c_enum_descriptor_get_value_by_name(const ProtobufCEnumDescriptor *desc,
- unsigned count = desc->n_value_names;
- unsigned mid = start + count / 2;
- int rv = strcmp(desc->values_by_name[mid].name, name);
- return desc->values + desc->values_by_name[mid].index;
- count = start + count - (mid + 1);
- if (strcmp(desc->values_by_name[start].name, name) == 0)
- return desc->values + desc->values_by_name[start].index;
-const ProtobufCEnumValue *
-protobuf_c_enum_descriptor_get_value(const ProtobufCEnumDescriptor *desc,
- int rv = int_range_lookup(desc->n_value_ranges, desc->value_ranges, value);
- return desc->values + rv;
-const ProtobufCFieldDescriptor *
-protobuf_c_message_descriptor_get_field_by_name(const ProtobufCMessageDescriptor *desc,
- unsigned count = desc->n_fields;
- const ProtobufCFieldDescriptor *field;
- unsigned mid = start + count / 2;
- field = desc->fields + desc->fields_sorted_by_name[mid];
- rv = strcmp(field->name, name);
- count = start + count - (mid + 1);
- field = desc->fields + desc->fields_sorted_by_name[start];
- if (strcmp(field->name, name) == 0)
-const ProtobufCFieldDescriptor *
-protobuf_c_message_descriptor_get_field(const ProtobufCMessageDescriptor *desc,
- int rv = int_range_lookup(desc->n_field_ranges,desc->field_ranges, value);
- return desc->fields + rv;
-const ProtobufCMethodDescriptor *
-protobuf_c_service_descriptor_get_method_by_name(const ProtobufCServiceDescriptor *desc,
- unsigned count = desc->n_methods;
- unsigned mid = start + count / 2;
- unsigned mid_index = desc->method_indices_by_name[mid];
- const char *mid_name = desc->methods[mid_index].name;
- int rv = strcmp(mid_name, name);
- return desc->methods + desc->method_indices_by_name[mid];
- count = start + count - (mid + 1);
- if (strcmp(desc->methods[desc->method_indices_by_name[start]].name, name) == 0)
- return desc->methods + desc->method_indices_by_name[start];
--- a/libpurple/protocols/gg/lib/protobuf-c.h Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1078 +0,0 @@
- * Copyright (c) 2008-2014, Dave Benson and the protobuf-c authors.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- * \mainpage Introduction
- * This is [protobuf-c], a C implementation of [Protocol Buffers].
- * This file defines the public API for the `libprotobuf-c` support library.
- * This API includes interfaces that can be used directly by client code as well
- * as the interfaces used by the code generated by the `protoc-c` compiler.
- * The `libprotobuf-c` support library performs the actual serialization and
- * deserialization of Protocol Buffers messages. It interacts with structures,
- * definitions, and metadata generated by the `protoc-c` compiler from .proto
- * \authors Dave Benson and the `protobuf-c` authors.
- * \copyright 2008-2014. Licensed under the terms of the [BSD-2-Clause] license.
- * [protobuf-c]: https://github.com/protobuf-c/protobuf-c
- * [Protocol Buffers]: https://developers.google.com/protocol-buffers/
- * [BSD-2-Clause]: http://opensource.org/licenses/BSD-2-Clause
- * \page gencode Generated Code
- * For each enum, we generate a C enum. For each message, we generate a C
- * structure which can be cast to a `ProtobufCMessage`.
- * For each enum and message, we generate a descriptor object that allows us to
- * implement a kind of reflection on the structures.
- * First, some naming conventions:
- * - The name of the type for enums and messages and services is camel case
- * (meaning WordsAreCrammedTogether) except that double underscores are used
- * to delimit scopes. For example, the following `.proto` file:
- optional int32 val = 1;
- * would generate a C type `Foo__Bar__BazBah`.
- * - Identifiers for functions and globals are all lowercase, with camel case
- * words separated by single underscores. For example, one of the function
- * prototypes generated by `protoc-c` for the above example:
- foo__bar__baz_bah__unpack
- (ProtobufCAllocator *allocator,
- * - Identifiers for enum values contain an uppercase prefix which embeds the
- * package name and the enum type name.
- * - A double underscore is used to separate further components of identifier
- * For example, in the name of the unpack function above, the package name
- * `foo.bar` has become `foo__bar`, the message name BazBah has become
- * `baz_bah`, and the method name is `unpack`. These are all joined with double
- * underscores to form the C identifier `foo__bar__baz_bah__unpack`.
- * We also generate descriptor objects for messages and enums. These are
- * declared in the `.pb-c.h` files:
-extern const ProtobufCMessageDescriptor foo__bar__baz_bah__descriptor;
- * The message structures all begin with `ProtobufCMessageDescriptor *` which is
- * sufficient to allow them to be cast to `ProtobufCMessage`.
- * For each message defined in a `.proto` file, we generate a number of
- * functions. Each function name contains a prefix based on the package name and
- * message name in order to make it a unique C identifier.
- * - `unpack()`. Unpacks data for a particular message format. Note that the
- * `allocator` parameter is usually `NULL` to indicate that the system's
- * `malloc()` and `free()` functions should be used for dynamically allocating
- foo__bar__baz_bah__unpack
- (ProtobufCAllocator *allocator,
- * - `free_unpacked()`. Frees a message object obtained with the `unpack()`
-void foo__bar__baz_bah__free_unpacked
- (Foo__Bar__BazBah *message,
- ProtobufCAllocator *allocator);
- * - `get_packed_size()`. Calculates the length in bytes of the serialized
- * representation of the message object.
-size_t foo__bar__baz_bah__get_packed_size
- (const Foo__Bar__BazBah *message);
- * - `pack()`. Pack a message object into a preallocated buffer. Assumes that
- * the buffer is large enough. (Use `get_packed_size()` first.)
-size_t foo__bar__baz_bah__pack
- (const Foo__Bar__BazBah *message,
- * - `pack_to_buffer()`. Packs a message into a "virtual buffer". This is an
- * object which defines an "append bytes" callback to consume data as it is
-size_t foo__bar__baz_bah__pack_to_buffer
- (const Foo__Bar__BazBah *message,
- ProtobufCBuffer *buffer);
- * \page pack Packing and unpacking messages
- * To pack a message, first compute the packed size of the message with
- * protobuf_c_message_get_packed_size(), then allocate a buffer of at least
- * that size, then call protobuf_c_message_pack().
- * Alternatively, a message can be serialized without calculating the final size
- * first. Use the protobuf_c_message_pack_to_buffer() function and provide a
- * ProtobufCBuffer object which implements an "append" method that consumes
- * To unpack a message, call the protobuf_c_message_unpack() function. The
- * result can be cast to an object of the type that matches the descriptor for
- * The result of unpacking a message should be freed with
- * protobuf_c_message_free_unpacked().
-# define PROTOBUF_C__BEGIN_DECLS extern "C" {
-# define PROTOBUF_C__END_DECLS }
-# define PROTOBUF_C__BEGIN_DECLS
-# define PROTOBUF_C__END_DECLS
-#if defined(_WIN32) && defined(PROTOBUF_C_USE_SHARED_LIB)
-# ifdef PROTOBUF_C_EXPORT
-# define PROTOBUF_C__API __declspec(dllexport)
-# define PROTOBUF_C__API __declspec(dllimport)
-# define PROTOBUF_C__API
-#if !defined(PROTOBUF_C__NO_DEPRECATED) && \
- ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
-# define PROTOBUF_C__DEPRECATED __attribute__((__deprecated__))
-# define PROTOBUF_C__DEPRECATED
-#ifndef PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE
- #define PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(enum_name) \
- , _##enum_name##_IS_INT_SIZE = INT_MAX
-#define PROTOBUF_C__SERVICE_DESCRIPTOR_MAGIC 0x14159bc3
-#define PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC 0x28aaeef9
-#define PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC 0x114315af
- * \defgroup api Public API
- * This is the public API for `libprotobuf-c`. These interfaces are stable and
- * subject to Semantic Versioning guarantees.
- * Values for the `flags` word in `ProtobufCFieldDescriptor`.
- /** Set if the field is repeated and marked with the `packed` option. */
- PROTOBUF_C_FIELD_FLAG_PACKED = (1 << 0),
- /** Set if the field is marked with the `deprecated` option. */
- PROTOBUF_C_FIELD_FLAG_DEPRECATED = (1 << 1),
- * \see [Defining A Message Type] in the Protocol Buffers documentation.
- * [Defining A Message Type]:
- * https://developers.google.com/protocol-buffers/docs/proto#simple
- /** A well-formed message must have exactly one of this field. */
- PROTOBUF_C_LABEL_REQUIRED,
- * A well-formed message can have zero or one of this field (but not
- PROTOBUF_C_LABEL_OPTIONAL,
- * This field can be repeated any number of times (including zero) in a
- * well-formed message. The order of the repeated values will be
- PROTOBUF_C_LABEL_REPEATED,
- * \see [Scalar Value Types] in the Protocol Buffers documentation.
- * [Scalar Value Types]:
- * https://developers.google.com/protocol-buffers/docs/proto#scalar
- PROTOBUF_C_TYPE_INT32, /**< int32 */
- PROTOBUF_C_TYPE_SINT32, /**< signed int32 */
- PROTOBUF_C_TYPE_SFIXED32, /**< signed int32 (4 bytes) */
- PROTOBUF_C_TYPE_INT64, /**< int64 */
- PROTOBUF_C_TYPE_SINT64, /**< signed int64 */
- PROTOBUF_C_TYPE_SFIXED64, /**< signed int64 (8 bytes) */
- PROTOBUF_C_TYPE_UINT32, /**< unsigned int32 */
- PROTOBUF_C_TYPE_FIXED32, /**< unsigned int32 (4 bytes) */
- PROTOBUF_C_TYPE_UINT64, /**< unsigned int64 */
- PROTOBUF_C_TYPE_FIXED64, /**< unsigned int64 (8 bytes) */
- PROTOBUF_C_TYPE_FLOAT, /**< float */
- PROTOBUF_C_TYPE_DOUBLE, /**< double */
- PROTOBUF_C_TYPE_BOOL, /**< boolean */
- PROTOBUF_C_TYPE_ENUM, /**< enumerated type */
- PROTOBUF_C_TYPE_STRING, /**< UTF-8 or ASCII string */
- PROTOBUF_C_TYPE_BYTES, /**< arbitrary byte sequence */
- PROTOBUF_C_TYPE_MESSAGE, /**< nested message */
- * \see [Message Structure] in the Protocol Buffers documentation.
- * https://developers.google.com/protocol-buffers/docs/encoding#structure
- PROTOBUF_C_WIRE_TYPE_VARINT = 0,
- PROTOBUF_C_WIRE_TYPE_64BIT = 1,
- PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED = 2,
- /* "Start group" and "end group" wire types are unsupported. */
- PROTOBUF_C_WIRE_TYPE_32BIT = 5,
-struct ProtobufCAllocator;
-struct ProtobufCBinaryData;
-struct ProtobufCBufferSimple;
-struct ProtobufCEnumDescriptor;
-struct ProtobufCEnumValue;
-struct ProtobufCEnumValueIndex;
-struct ProtobufCFieldDescriptor;
-struct ProtobufCIntRange;
-struct ProtobufCMessage;
-struct ProtobufCMessageDescriptor;
-struct ProtobufCMessageUnknownField;
-struct ProtobufCMethodDescriptor;
-struct ProtobufCService;
-struct ProtobufCServiceDescriptor;
-typedef struct ProtobufCAllocator ProtobufCAllocator;
-typedef struct ProtobufCBinaryData ProtobufCBinaryData;
-typedef struct ProtobufCBuffer ProtobufCBuffer;
-typedef struct ProtobufCBufferSimple ProtobufCBufferSimple;
-typedef struct ProtobufCEnumDescriptor ProtobufCEnumDescriptor;
-typedef struct ProtobufCEnumValue ProtobufCEnumValue;
-typedef struct ProtobufCEnumValueIndex ProtobufCEnumValueIndex;
-typedef struct ProtobufCFieldDescriptor ProtobufCFieldDescriptor;
-typedef struct ProtobufCIntRange ProtobufCIntRange;
-typedef struct ProtobufCMessage ProtobufCMessage;
-typedef struct ProtobufCMessageDescriptor ProtobufCMessageDescriptor;
-typedef struct ProtobufCMessageUnknownField ProtobufCMessageUnknownField;
-typedef struct ProtobufCMethodDescriptor ProtobufCMethodDescriptor;
-typedef struct ProtobufCService ProtobufCService;
-typedef struct ProtobufCServiceDescriptor ProtobufCServiceDescriptor;
-typedef int protobuf_c_boolean;
-typedef void (*ProtobufCClosure)(const ProtobufCMessage *, void *closure_data);
-typedef void (*ProtobufCMessageInit)(ProtobufCMessage *);
-typedef void (*ProtobufCServiceDestroy)(ProtobufCService *);
- * Structure for defining a custom memory allocator.
-struct ProtobufCAllocator {
- /** Function to allocate memory. */
- void *(*alloc)(void *allocator_data, size_t size);
- /** Function to free memory. */
- void (*free)(void *allocator_data, void *pointer);
- /** Opaque pointer passed to `alloc` and `free` functions. */
- * Structure for the protobuf `bytes` scalar type.
- * The data contained in a `ProtobufCBinaryData` is an arbitrary sequence of
- * bytes. It may contain embedded `NUL` characters and is not required to be
-struct ProtobufCBinaryData {
- size_t len; /**< Number of bytes in the `data` field. */
- uint8_t *data; /**< Data bytes. */
- * Structure for defining a virtual append-only buffer. Used by
- * protobuf_c_message_pack_to_buffer() to abstract the consumption of serialized
- * `ProtobufCBuffer` "subclasses" may be defined on the stack. For example, to
- * write to a `FILE` object:
-my_buffer_file_append(ProtobufCBuffer *buffer,
- BufferAppendToFile *file_buf = (BufferAppendToFile *) buffer;
- fwrite(data, len, 1, file_buf->fp); // XXX: No error handling!
- * To use this new type of ProtobufCBuffer, it could be called as follows:
-BufferAppendToFile tmp = {0};
-tmp.base.append = my_buffer_file_append;
-protobuf_c_message_pack_to_buffer(&message, &tmp);
-struct ProtobufCBuffer {
- /** Append function. Consumes the `len` bytes stored at `data`. */
- void (*append)(ProtobufCBuffer *buffer,
- * Simple buffer "subclass" of `ProtobufCBuffer`.
- * A `ProtobufCBufferSimple` object is declared on the stack and uses a
- * scratch buffer provided by the user for the initial allocation. It performs
- * exponential resizing, using dynamically allocated memory. A
- * `ProtobufCBufferSimple` object can be created and used as follows:
-ProtobufCBufferSimple simple = PROTOBUF_C_BUFFER_SIMPLE_INIT(pad);
-ProtobufCBuffer *buffer = (ProtobufCBuffer *) &simple;
- * `buffer` can now be used with `protobuf_c_message_pack_to_buffer()`. Once a
- * message has been serialized to a `ProtobufCBufferSimple` object, the
- * serialized data bytes can be accessed from the `.data` field.
- * To free the memory allocated by a `ProtobufCBufferSimple` object, if any,
- * call PROTOBUF_C_BUFFER_SIMPLE_CLEAR() on the object, for example:
-PROTOBUF_C_BUFFER_SIMPLE_CLEAR(&simple);
- * \see PROTOBUF_C_BUFFER_SIMPLE_INIT
- * \see PROTOBUF_C_BUFFER_SIMPLE_CLEAR
-struct ProtobufCBufferSimple {
- /** Number of bytes allocated in `data`. */
- /** Number of bytes currently stored in `data`. */
- /** Whether `data` must be freed. */
- protobuf_c_boolean must_free_data;
- /** Allocator to use. May be NULL to indicate the system allocator. */
- ProtobufCAllocator *allocator;
- * Describes an enumeration as a whole, with all of its values.
-struct ProtobufCEnumDescriptor {
- /** Magic value checked to ensure that the API is used correctly. */
- /** The qualified name (e.g., "namespace.Type"). */
- /** The unqualified name as given in the .proto file (e.g., "Type"). */
- const char *short_name;
- /** Identifier used in generated C code. */
- /** The dot-separated namespace. */
- const char *package_name;
- /** Number elements in `values`. */
- /** Array of distinct values, sorted by numeric value. */
- const ProtobufCEnumValue *values;
- /** Number of elements in `values_by_name`. */
- unsigned n_value_names;
- /** Array of named values, including aliases, sorted by name. */
- const ProtobufCEnumValueIndex *values_by_name;
- /** Number of elements in `value_ranges`. */
- unsigned n_value_ranges;
- /** Value ranges, for faster lookups by numeric value. */
- const ProtobufCIntRange *value_ranges;
- /** Reserved for future use. */
- /** Reserved for future use. */
- /** Reserved for future use. */
- /** Reserved for future use. */
- * Represents a single value of an enumeration.
-struct ProtobufCEnumValue {
- /** The string identifying this value in the .proto file. */
- /** The string identifying this value in generated C code. */
- /** The numeric value assigned in the .proto file. */
- * Used by `ProtobufCEnumDescriptor` to look up enum values.
-struct ProtobufCEnumValueIndex {
- /** Name of the enum value. */
- /** Index into values[] array. */
- * Describes a single field in a message.
-struct ProtobufCFieldDescriptor {
- /** Name of the field as given in the .proto file. */
- /** Tag value of the field as given in the .proto file. */
- /** Whether the field is `REQUIRED`, `OPTIONAL`, or `REPEATED`. */
- /** The type of the field. */
- * The offset in bytes of the message's C structure's quantifier field
- * (the `has_MEMBER` field for optional members or the `n_MEMBER` field
- * for repeated members.
- unsigned quantifier_offset;
- * The offset in bytes into the message's C structure for the member
- * A type-specific descriptor.
- * If `type` is `PROTOBUF_C_TYPE_ENUM`, then `descriptor` points to the
- * corresponding `ProtobufCEnumDescriptor`.
- * If `type` is `PROTOBUF_C_TYPE_MESSAGE`, then `descriptor` points to
- * the corresponding `ProtobufCMessageDescriptor`.
- * Otherwise this field is NULL.
- const void *descriptor; /* for MESSAGE and ENUM types */
- /** The default value for this field, if defined. May be NULL. */
- const void *default_value;
- * A flag word. Zero or more of the bits defined in the
- * `ProtobufCFieldFlag` enum may be set.
- /** Reserved for future use. */
- unsigned reserved_flags;
- /** Reserved for future use. */
- /** Reserved for future use. */
- * Helper structure for optimizing int => index lookups in the case
- * where the keys are mostly consecutive values, as they presumably are for
- * The data structures requires that the values in the original array are
-struct ProtobufCIntRange {
- * NOTE: the number of values in the range can be inferred by looking
- * at the next element's orig_index. A dummy element is added to make
- * An instance of a message.
- * `ProtobufCMessage` is a light-weight "base class" for all messages.
- * In particular, `ProtobufCMessage` doesn't have any allocation policy
- * associated with it. That's because it's common to create `ProtobufCMessage`
- * objects on the stack. In fact, that's what we recommend for sending messages.
- * If the object is allocated from the stack, you can't really have a memory
- * This means that calls to functions like protobuf_c_message_unpack() which
- * return a `ProtobufCMessage` must be paired with a call to a free function,
- * like protobuf_c_message_free_unpacked().
-struct ProtobufCMessage {
- /** The descriptor for this message type. */
- const ProtobufCMessageDescriptor *descriptor;
- /** The number of elements in `unknown_fields`. */
- unsigned n_unknown_fields;
- /** The fields that weren't recognized by the parser. */
- ProtobufCMessageUnknownField *unknown_fields;
-struct ProtobufCMessageDescriptor {
- /** Magic value checked to ensure that the API is used correctly. */
- /** The qualified name (e.g., "namespace.Type"). */
- /** The unqualified name as given in the .proto file (e.g., "Type"). */
- const char *short_name;
- /** Identifier used in generated C code. */
- /** The dot-separated namespace. */
- const char *package_name;
- * Size in bytes of the C structure representing an instance of this
- /** Number of elements in `fields`. */
- /** Field descriptors, sorted by tag number. */
- const ProtobufCFieldDescriptor *fields;
- /** Used for looking up fields by name. */
- const unsigned *fields_sorted_by_name;
- /** Number of elements in `field_ranges`. */
- unsigned n_field_ranges;
- /** Used for looking up fields by id. */
- const ProtobufCIntRange *field_ranges;
- /** Message initialisation function. */
- ProtobufCMessageInit message_init;
- /** Reserved for future use. */
- /** Reserved for future use. */
- /** Reserved for future use. */
- * An unknown message field.
-struct ProtobufCMessageUnknownField {
- /** The wire type of the field. */
- ProtobufCWireType wire_type;
- /** Number of bytes in `data`. */
-struct ProtobufCMethodDescriptor {
- /** Input message descriptor. */
- const ProtobufCMessageDescriptor *input;
- /** Output message descriptor. */
- const ProtobufCMessageDescriptor *output;
-struct ProtobufCService {
- /** Service descriptor. */
- const ProtobufCServiceDescriptor *descriptor;
- /** Function to invoke the service. */
- void (*invoke)(ProtobufCService *service,
- const ProtobufCMessage *input,
- ProtobufCClosure closure,
- /** Function to destroy the service. */
- void (*destroy)(ProtobufCService *service);
-struct ProtobufCServiceDescriptor {
- /** Magic value checked to ensure that the API is used correctly. */
- /** Short version of service name. */
- const char *short_name;
- /** C identifier for the service name. */
- /** Number of elements in `methods`. */
- /** Method descriptors, in the order defined in the .proto file. */
- const ProtobufCMethodDescriptor *methods;
- /** Sort index of methods. */
- const unsigned *method_indices_by_name;
- * Get the version of the protobuf-c library. Note that this is the version of
- * the library linked against, not the version of the headers compiled against.
- * \return A string containing the version number of protobuf-c.
-protobuf_c_version(void);
- * Get the version of the protobuf-c library. Note that this is the version of
- * the library linked against, not the version of the headers compiled against.
- * \return A 32 bit unsigned integer containing the version number of
- * protobuf-c, represented in base-10 as (MAJOR*1E6) + (MINOR*1E3) + PATCH.
-protobuf_c_version_number(void);
- * The version of the protobuf-c headers, represented as a string using the same
- * format as protobuf_c_version().
-#define PROTOBUF_C_VERSION "1.0.2"
- * The version of the protobuf-c headers, represented as an integer using the
- * same format as protobuf_c_version_number().
-#define PROTOBUF_C_VERSION_NUMBER 1000002
- * The minimum protoc-c version which works with the current version of the
-#define PROTOBUF_C_MIN_COMPILER_VERSION 1000000
- * Look up a `ProtobufCEnumValue` from a `ProtobufCEnumDescriptor` by name.
- * The `ProtobufCEnumDescriptor` object.
- * The `name` field from the corresponding `ProtobufCEnumValue` object to
- * A `ProtobufCEnumValue` object.
-const ProtobufCEnumValue *
-protobuf_c_enum_descriptor_get_value_by_name(
- const ProtobufCEnumDescriptor *desc,
- * Look up a `ProtobufCEnumValue` from a `ProtobufCEnumDescriptor` by numeric
- * The `ProtobufCEnumDescriptor` object.
- * The `value` field from the corresponding `ProtobufCEnumValue` object to
- * A `ProtobufCEnumValue` object.
-const ProtobufCEnumValue *
-protobuf_c_enum_descriptor_get_value(
- const ProtobufCEnumDescriptor *desc,
- * Look up a `ProtobufCFieldDescriptor` from a `ProtobufCMessageDescriptor` by
- * the name of the field.
- * The `ProtobufCMessageDescriptor` object.
- * The name of the field.
- * A `ProtobufCFieldDescriptor` object.
-const ProtobufCFieldDescriptor *
-protobuf_c_message_descriptor_get_field_by_name(
- const ProtobufCMessageDescriptor *desc,
- * Look up a `ProtobufCFieldDescriptor` from a `ProtobufCMessageDescriptor` by
- * the tag value of the field.
- * The `ProtobufCMessageDescriptor` object.
- * The tag value of the field.
- * A `ProtobufCFieldDescriptor` object.
-const ProtobufCFieldDescriptor *
-protobuf_c_message_descriptor_get_field(
- const ProtobufCMessageDescriptor *desc,
- * Determine the number of bytes required to store the serialised message.
- * The message object to serialise.
-protobuf_c_message_get_packed_size(const ProtobufCMessage *message);
- * Serialise a message from its in-memory representation.
- * This function stores the serialised bytes of the message in a pre-allocated
- * The message object to serialise.
- * Buffer to store the bytes of the serialised message. This buffer must
- * have enough space to store the packed message. Use
- * protobuf_c_message_get_packed_size() to determine the number of bytes
- * Number of bytes stored in `out`.
-protobuf_c_message_pack(const ProtobufCMessage *message, uint8_t *out);
- * Serialise a message from its in-memory representation to a virtual buffer.
- * This function calls the `append` method of a `ProtobufCBuffer` object to
- * consume the bytes generated by the serialiser.
- * The message object to serialise.
- * The virtual buffer object.
- * Number of bytes passed to the virtual buffer.
-protobuf_c_message_pack_to_buffer(
- const ProtobufCMessage *message,
- ProtobufCBuffer *buffer);
- * Unpack a serialised message into an in-memory representation.
- * The message descriptor.
- * `ProtobufCAllocator` to use for memory allocation. May be NULL to
- * specify the default allocator.
- * Length in bytes of the serialised message.
- * Pointer to the serialised message.
- * An unpacked message object.
- * If an error occurred during unpacking.
-protobuf_c_message_unpack(
- const ProtobufCMessageDescriptor *descriptor,
- ProtobufCAllocator *allocator,
- * Free an unpacked message object.
- * This function should be used to deallocate the memory used by a call to
- * protobuf_c_message_unpack().
- * The message object to free.
- * `ProtobufCAllocator` to use for memory deallocation. May be NULL to
- * specify the default allocator.
-protobuf_c_message_free_unpacked(
- ProtobufCMessage *message,
- ProtobufCAllocator *allocator);
- * Check the validity of a message object.
- * Makes sure all required fields (`PROTOBUF_C_LABEL_REQUIRED`) are present.
- * Recursively checks nested messages.
-protobuf_c_message_check(const ProtobufCMessage *);
-/** Message initialiser. */
-#define PROTOBUF_C_MESSAGE_INIT(descriptor) { descriptor, 0, NULL }
- * Initialise a message object from a message descriptor.
- * Allocated block of memory of size `descriptor->sizeof_message`.
-protobuf_c_message_init(
- const ProtobufCMessageDescriptor *descriptor,
- * The service object to free.
-protobuf_c_service_destroy(ProtobufCService *service);
- * Look up a `ProtobufCMethodDescriptor` by name.
- * A `ProtobufCMethodDescriptor` object.
-const ProtobufCMethodDescriptor *
-protobuf_c_service_descriptor_get_method_by_name(
- const ProtobufCServiceDescriptor *desc,
- * Initialise a `ProtobufCBufferSimple` object.
-#define PROTOBUF_C_BUFFER_SIMPLE_INIT(array_of_bytes) \
- { protobuf_c_buffer_simple_append }, \
- sizeof(array_of_bytes), \
- * Clear a `ProtobufCBufferSimple` object, freeing any allocated memory.
-#define PROTOBUF_C_BUFFER_SIMPLE_CLEAR(simp_buf) \
- if ((simp_buf)->must_free_data) { \
- if ((simp_buf)->allocator != NULL) \
- (simp_buf)->allocator->free( \
- (simp_buf)->allocator, \
- free((simp_buf)->data); \
- * The `append` method for `ProtobufCBufferSimple`.
- * The buffer object to append to. Must actually be a
- * `ProtobufCBufferSimple` object.
- * Number of bytes in `data`.
-protobuf_c_buffer_simple_append(
- ProtobufCBuffer *buffer,
- const unsigned char *data);
-protobuf_c_service_generated_init(
- ProtobufCService *service,
- const ProtobufCServiceDescriptor *descriptor,
- ProtobufCServiceDestroy destroy);
-protobuf_c_service_invoke_internal(
- ProtobufCService *service,
- const ProtobufCMessage *input,
- ProtobufCClosure closure,
-#endif /* PROTOBUF_C_H */
--- a/libpurple/protocols/gg/lib/protobuf.c Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,153 +0,0 @@
- * (C) Copyright 2012 Tomek Wasilczyk <www.wasilczyk.pl>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
- * \brief Funkcje pomocnicze do obsługi formatu protocol buffers
-#define GG_PROTOBUFF_UIN_MAXLEN 15
-struct _gg_protobuf_uin_buff
- char data[GG_PROTOBUFF_UIN_MAXLEN + 1 + 2];
-void gg_protobuf_expected(struct gg_session *gs, const char *field_name,
- uint32_t value, uint32_t expected)
- if (value == expected) {
- gg_debug_session(gs, GG_DEBUG_WARNING, "// gg_packet: field %s was "
- "expected to be %#x, but its value was %#x\n",
- field_name, expected, value);
-int gg_protobuf_valid_chknull(struct gg_session *gs, const char *msg_name,
- gg_debug_session(gs, GG_DEBUG_ERROR, "// gg_protobuf: couldn't "
- "unpack %s message\n", msg_name);
-int gg_protobuf_valid_chkunknown(struct gg_session *gs, const char *msg_name,
- ProtobufCMessage *base)
- if (base->n_unknown_fields > 0) {
- gg_debug_session(gs, GG_DEBUG_WARNING, "// gg_protobuf: message"
- " %s had %d unknown field(s)\n",
- msg_name, base->n_unknown_fields);
-int gg_protobuf_send_ex(struct gg_session *gs, struct gg_event *ge, int type,
- void *msg, gg_protobuf_size_cb_t size_cb,
- gg_protobuf_pack_cb_t pack_cb)
- enum gg_failure_t failure;
- gg_debug_session(gs, GG_DEBUG_ERROR, "// gg_protobuf_send: out "
- "of memory - tried to allocate %" GG_SIZE_FMT
- " bytes for %#x packet\n", len, type);
- failure = GG_FAILURE_INTERNAL;
- succ = (-1 != gg_send_packet(gs, type, buffer, len, NULL));
- failure = GG_FAILURE_WRITING;
- gg_debug_session(gs, GG_DEBUG_ERROR,
- "// gg_protobuf_send: sending packet %#x "
- "failed. (errno=%d, %s)\n", type, errno,
- gg_connection_failure(gs, ge, failure);
-void gg_protobuf_set_uin(ProtobufCBinaryData *dst, uin_t uin, gg_protobuf_uin_buff_t *buff)
- static gg_protobuf_uin_buff_t static_buffer;
- uin_str = buff->data + 2;
- uin_len = snprintf(uin_str, GG_PROTOBUFF_UIN_MAXLEN + 1, "%u", uin);
- buff->data[0] = 0x01; /* magic: 0x00 lub 0x01 */
- buff->data[1] = uin_len;
- dst->len = uin_len + 2;
- dst->data = (uint8_t*)&buff->data;
-uin_t gg_protobuf_get_uin(ProtobufCBinaryData uin_data)
- magic = (uin_data.len > 0) ? uin_data.data[0] : 0;
- uin_len = (uin_data.len > 1) ? uin_data.data[1] : 0;
- if (uin_data.len != uin_len + 2 || uin_len > 10) {
- gg_debug(GG_DEBUG_ERROR, "// gg_protobuf_get_uin: "
- gg_debug(GG_DEBUG_WARNING, "// gg_protobuf_get_uin: "
- "unexpected magic value=%#x\n", magic);
- uin_str = (char*)(uin_data.data + 2);
- uin = gg_str_to_uin(uin_str, uin_len);
- gg_debug(GG_DEBUG_ERROR, "// gg_protobuf_get_uin: "
--- a/libpurple/protocols/gg/lib/protobuf.h Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
- * (C) Copyright 2012 Tomek Wasilczyk <www.wasilczyk.pl>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-#ifndef LIBGADU_PROTOBUF_H
-#define LIBGADU_PROTOBUF_H
-#ifdef GG_CONFIG_HAVE_PROTOBUF_C
-#include <protobuf-c/protobuf-c.h>
-typedef size_t (*gg_protobuf_size_cb_t)(const void *message);
-typedef size_t (*gg_protobuf_pack_cb_t)(const void *message, uint8_t *out);
-typedef struct _gg_protobuf_uin_buff gg_protobuf_uin_buff_t;
-/* Ostatni warunek (msg != NULL) jest tylko po to, żeby uciszyć analizę
- * statyczną (zawiera się w pierwszym). */
-#define GG_PROTOBUF_VALID(gs, name, msg) \
- (gg_protobuf_valid_chknull(gs, name, msg == NULL) && \
- gg_protobuf_valid_chkunknown(gs, name, &msg->base) && \
-#define GG_PROTOBUF_SEND(gs, ge, packet_type, msg_type, msg) \
- gg_protobuf_send_ex(gs, ge, packet_type, &msg, \
- (gg_protobuf_size_cb_t) msg_type ## __get_packed_size, \
- (gg_protobuf_pack_cb_t) msg_type ## __pack)
-void gg_protobuf_expected(struct gg_session *gs, const char *field_name,
- uint32_t value, uint32_t expected);
-int gg_protobuf_valid_chknull(struct gg_session *gs, const char *msg_name,
-int gg_protobuf_valid_chkunknown(struct gg_session *gs, const char *msg_name,
- ProtobufCMessage *base);
-int gg_protobuf_send_ex(struct gg_session *gs, struct gg_event *ge, int type,
- void *msg, gg_protobuf_size_cb_t size_cb,
- gg_protobuf_pack_cb_t pack_cb);
-void gg_protobuf_set_uin(ProtobufCBinaryData *dst, uin_t uin, gg_protobuf_uin_buff_t *buff);
-uin_t gg_protobuf_get_uin(ProtobufCBinaryData uin_data);
-#endif /* LIBGADU_PROTOBUF_H */
--- a/libpurple/protocols/gg/lib/protocol.h Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,411 +0,0 @@
- * (C) Copyright 2009-2010 Jakub Zawadzki <darkjames@darkjames.ath.cx>
- * Bartłomiej Zimoń <uzi18@o2.pl>
- * Wojtek Kaniewski <wojtekka@irc.pl>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-#ifndef LIBGADU_PROTOCOL_H
-#define LIBGADU_PROTOCOL_H
-#define GG_LOGIN80BETA 0x0029
-#define GG_LOGIN80 0x0031
-#define GG_LOGIN105 0x0083
-#undef GG_FEATURE_STATUS80BETA
-#undef GG_FEATURE_STATUS80
-#define GG_FEATURE_STATUS80BETA 0x01
-#define GG_FEATURE_MSG80 0x02
-#define GG_FEATURE_STATUS80 0x05
-#define GG_DEFAULT_HOST_WHITE_LIST { "gadu-gadu.pl", "gg.pl", NULL }
-#define GG8_VERSION "Gadu-Gadu Client Build "
-#define GG11_VERSION "GG-Phoenix/"
-#define GG11_TARGET " (BUILD;WINNT_x86-msvc;rv:11.0,pl;release;standard) (OS;Windows;Windows NT 6.1)"
- uint32_t uin; /* mój numerek */
- uint8_t language[2]; /* język: GG8_LANG */
- uint8_t hash_type; /* rodzaj hashowania hasła */
- uint8_t hash[64]; /* hash hasła dopełniony zerami */
- uint32_t status; /* status na dzień dobry */
- uint32_t flags; /* flagi (przeznaczenie nieznane) */
- uint32_t features; /* opcje protokołu (GG8_FEATURES) */
- uint32_t local_ip; /* mój adres ip */
- uint16_t local_port; /* port, na którym słucham */
- uint32_t external_ip; /* zewnętrzny adres ip (???) */
- uint16_t external_port; /* zewnętrzny port (???) */
- uint8_t image_size; /* maksymalny rozmiar grafiki w KiB */
- uint8_t dunno2; /* 0x64 */
-#define GG_LOGIN_HASH_TYPE_INVALID 0x0016
-#define GG_LOGIN80_OK 0x0035
-#define GG_LOGIN110_OK 0x009d
- * Logowanie powiodło się (pakiet \c GG_LOGIN80_OK)
- uint32_t unknown1; /* 0x00000001 */
- * Logowanie nie powiodło się (pakiet \c GG_LOGIN80_FAILED)
-#define GG_LOGIN80_FAILED 0x0043
-struct gg_login80_failed {
- uint32_t unknown1; /* 0x00000001 */
-#define GG_NEW_STATUS80BETA 0x0028
-#define GG_NEW_STATUS80 0x0038
- * Zmiana stanu (pakiet \c GG_NEW_STATUS80)
-struct gg_new_status80 {
- uint32_t status; /**< Nowy status */
- uint32_t flags; /**< flagi (nieznane przeznaczenie) */
- uint32_t description_size; /**< rozmiar opisu */
-#define GG_NEW_STATUS105 0x0063
-#define GG_STATUS80BETA 0x002a
-#define GG_NOTIFY_REPLY80BETA 0x002b
-#define GG_STATUS80 0x0036
-#define GG_NOTIFY_REPLY80 0x0037
-struct gg_notify_reply80 {
- uint32_t uin; /* numerek plus flagi w najstarszym bajcie */
- uint32_t status; /* status danej osoby */
- uint32_t features; /* opcje protokołu */
- uint32_t remote_ip; /* adres IP bezpośrednich połączeń */
- uint16_t remote_port; /* port bezpośrednich połączeń */
- uint8_t image_size; /* maksymalny rozmiar obrazków w KB */
- uint8_t unknown1; /* 0x00 */
- uint32_t flags; /* flagi połączenia */
- uint32_t descr_len; /* rozmiar opisu */
-#define GG_SEND_MSG80 0x002d
-#define GG_RECV_MSG80 0x002e
-#define GG_DISCONNECT_ACK 0x000d
-#define GG_RECV_MSG_ACK 0x0046
-struct gg_recv_msg_ack {
-#define GG_USER_DATA 0x0044
-struct gg_user_data_user {
-#define GG_TYPING_NOTIFICATION 0x0059
-struct gg_typing_notification {
-#define GG_XML_ACTION 0x002c
-#define GG_RECV_OWN_MSG 0x005a
-#define GG_MULTILOGON_INFO 0x005b
-struct gg_multilogon_info {
-struct gg_multilogon_info_item {
- gg_multilogon_id_t conn_id;
-#define GG_MULTILOGON_DISCONNECT 0x0062
-struct gg_multilogon_disconnect {
- gg_multilogon_id_t conn_id;
-#define GG_MSG_CALLBACK 0x02 /**< Żądanie zwrotnego połączenia bezpośredniego */
-#define GG_MSG_OPTION_CONFERENCE 0x01
-#define GG_MSG_OPTION_ATTRIBUTES 0x02
-#define GG_MSG_OPTION_IMAGE_REQUEST 0x04
-#define GG_MSG_OPTION_IMAGE_REPLY 0x05
-#define GG_MSG_OPTION_IMAGE_REPLY_MORE 0x06
-#define GG_DCC7_ABORT 0x0025
- gg_dcc7_id_t id; /* identyfikator połączenia */
- uint32_t uin_from; /* numer nadawcy */
- uint32_t uin_to; /* numer odbiorcy */
-#define GG_DCC7_ABORTED 0x0025
-struct gg_dcc7_aborted {
- gg_dcc7_id_t id; /* identyfikator połączenia */
-#define GG_DCC7_VOICE_RETRIES 0x11 /* 17 powtorzen */
-#define GG_DCC7_RESERVED1 0xdeadc0de
-#define GG_DCC7_RESERVED2 0xdeadbeaf
-struct gg_dcc7_voice_auth {
- uint8_t type; /* 0x00 -> wysylanie ID
- * 0x01 -> potwierdzenie ID
- gg_dcc7_id_t id; /* identyfikator połączenia */
- uint32_t reserved1; /* GG_DCC7_RESERVED1 */
- uint32_t reserved2; /* GG_DCC7_RESERVED2 */
-/* Wyciszony mikrofon. Ten pakiet jest wysylany co 1s (jesli chcemy podtrzymac
-struct gg_dcc7_voice_nodata {
- uint8_t type; /* 0x02 */
- gg_dcc7_id_t id; /* identyfikator połączenia */
- uint32_t reserved1; /* GG_DCC7_RESERVED1 */
- uint32_t reserved2; /* GG_DCC7_RESERVED2 */
-struct gg_dcc7_voice_data {
- uint8_t type; /* 0x03 */
- uint32_t did; /* XXX: co ile zwieksza sie u nas id pakietu [uzywac 0x28] */
- uint32_t len; /* rozmiar strukturki - 1 (sizeof(type)) */
- uint32_t packet_id; /* numerek pakietu */
- uint32_t datalen; /* rozmiar danych */
- /* char data[]; */ /* ramki: albo gsm, albo speex, albo melp, albo inne. */
-struct gg_dcc7_voice_init {
- uint8_t type; /* 0x04 */
- uint32_t id; /* nr kroku [0x1 - 0x5] */
- uint32_t protocol; /* XXX: wersja protokolu (0x29, 0x2a, 0x2b) */
- uint32_t len; /* rozmiar sizeof(protocol)+sizeof(len)+
- * sizeof(data) = 0x08 + sizeof(data) */
- /* char data[]; */ /* reszta danych */
-struct gg_dcc7_voice_init_confirm {
- uint8_t type; /* 0x05 */
- uint32_t id; /* id tego co potwierdzamy [0x1 - 0x5] */
-#define GG_DCC7_RELAY_TYPE_SERVER 0x01 /* adres serwera, na który spytać o proxy */
-#define GG_DCC7_RELAY_TYPE_PROXY 0x08 /* adresy proxy, na które sie łączyć */
-#define GG_DCC7_RELAY_DUNNO1 0x02
-#define GG_DCC7_RELAY_REQUEST 0x0a
-struct gg_dcc7_relay_req {
- uint32_t magic; /* 0x0a */
- uint32_t len; /* długość całego pakietu */
- gg_dcc7_id_t id; /* identyfikator połączenia */
- uint16_t type; /* typ zapytania */
- uint16_t dunno1; /* 0x02 */
-#define GG_DCC7_RELAY_REPLY_RCOUNT 0x02
-#define GG_DCC7_RELAY_REPLY 0x0b
-struct gg_dcc7_relay_reply {
- uint32_t magic; /* 0x0b */
- uint32_t len; /* długość całego pakietu */
- uint32_t rcount; /* ilość serwerów */
-struct gg_dcc7_relay_reply_server {
- uint32_t addr; /* adres ip serwera */
- uint16_t port; /* port serwera */
- uint8_t family; /* rodzina adresów (na końcu?!) AF_INET=2 */
-#define GG_DCC7_WELCOME_SERVER 0xc0debabe
-struct gg_dcc7_welcome_server {
- uint32_t magic; /* 0xc0debabe */
- gg_dcc7_id_t id; /* identyfikator połączenia */
-struct gg_dcc7_welcome_p2p {
- gg_dcc7_id_t id; /* identyfikator połączenia */
-#define GG_TIMEOUT_DISCONNECT 5 /**< Maksymalny czas oczekiwania na rozłączenie */
-#define GG_USERLIST100_VERSION 0x5c
-struct gg_userlist100_version {
- uint32_t version; /* numer wersji listy kontaktów */
-#define GG_USERLIST100_REQUEST 0x0040
-struct gg_userlist100_request {
- uint8_t type; /* rodzaj żądania */
- uint32_t version; /* numer ostatniej znanej wersji listy kontaktów bądź 0 */
- uint8_t format_type; /* rodzaj żądanego typu formatu listy kontaktów */
- uint8_t unknown1; /* 0x01 */
-#define GG_USERLIST100_REPLY 0x41
-struct gg_userlist100_reply {
- uint8_t type; /* rodzaj odpowiedzi */
- uint32_t version; /* numer wersji listy kontaktów aktualnie przechowywanej przez serwer */
- uint8_t format_type; /* rodzaj przesyłanego typu formatu listy kontaktów */
- uint8_t unknown1; /* 0x01 */
- uint32_t participants_count;
-struct gg_chat_created {
-struct gg_chat_invite_ack {
- uint32_t unknown1; /* 0x00 */
- uint32_t unknown2; /* 0x10 */
-#define GG_ADD_NOTIFY105 0x007b
-#define GG_REMOVE_NOTIFY105 0x007c
-#define GG_EVENT110 0x0084
-#define GG_IMTOKEN 0x008c
-#define GG_ACCESS_INFO 0x008f
-#define GG_NOTIFY105_FIRST 0x0077
-#define GG_NOTIFY105_LAST 0x0078
-#define GG_NOTIFY105_LIST_EMPTY 0x0079
-#define GG_PONG110 0x00a1
-#define GG_OPTIONS 0x009b
-#define GG_SEND_MSG110 0x007d
-#define GG_RECV_MSG110 0x007e
-#define GG_RECV_OWN_MSG110 0x0082
-#define GG_ACK110 0x0086
-#define GG_SEND_MSG_ACK110 0x0087
-#define GG_CHAT_INFO 0x0093
-#define GG_CHAT_INFO_UPDATE 0x009e
-#define GG_CHAT_CREATED 0x0045
-#define GG_CHAT_INVITE_ACK 0x0047
-#define GG_CHAT_RECV_MSG 0x0088
-#define GG_CHAT_RECV_OWN_MSG 0x008e
-#define GG_CHAT_CREATE 0x0047
-#define GG_CHAT_INVITE 0x0090
-#define GG_CHAT_LEAVE 0x0052
-#define GG_CHAT_LEFT 0x0066
-#define GG_CHAT_SEND_MSG 0x008d
-#define GG_UIN_INFO 0x007a
-#define GG_TRANSFER_INFO 0x00a0
-#define GG_MAGIC_NOTIFICATION 0x009f
-#endif /* LIBGADU_PROTOCOL_H */
--- a/libpurple/protocols/gg/lib/pubdir.c Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,888 +0,0 @@
- * (C) Copyright 2001-2006 Wojtek Kaniewski <wojtekka@irc.pl>
- * Dawid Jarosz <dawjar@poczta.onet.pl>
- * Adam Wysocki <gophi@ekg.chmurka.net>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
- * \brief Obsługa katalogu publicznego
- * Rejestruje nowego użytkownika.
- * Wymaga wcześniejszego pobrania tokenu za pomocą \c gg_token().
- * \param email Adres e-mail
- * \param password Hasło
- * \param tokenid Identyfikator tokenu
- * \param tokenval Zawartość tokenu
- * \param async Flaga połączenia asynchronicznego
- * \return Struktura \c gg_http lub \c NULL w przypadku błędu
-struct gg_http *gg_register3(const char *email, const char *password,
- const char *tokenid, const char *tokenval, int async)
- char *__pwd, *__email, *__tokenid, *__tokenval, *form, *query;
- if (!email || !password || !tokenid || !tokenval) {
- gg_debug(GG_DEBUG_MISC, "=> register, NULL parameter\n");
- __pwd = gg_urlencode(password);
- __email = gg_urlencode(email);
- __tokenid = gg_urlencode(tokenid);
- __tokenval = gg_urlencode(tokenval);
- if (!__pwd || !__email || !__tokenid || !__tokenval) {
- gg_debug(GG_DEBUG_MISC, "=> register, not enough memory for form fields\n");
- form = gg_saprintf("pwd=%s&email=%s&tokenid=%s&tokenval=%s&code=%u",
- __pwd, __email, __tokenid, __tokenval,
- gg_http_hash("ss", email, password));
- gg_debug(GG_DEBUG_MISC, "=> register, not enough memory for form query\n");
- gg_debug(GG_DEBUG_MISC, "=> register, %s\n", form);
- "Host: " GG_REGISTER_HOST "\r\n"
- "Content-Type: application/x-www-form-urlencoded\r\n"
- "User-Agent: " GG_HTTP_USERAGENT "\r\n"
- "Content-Length: %d\r\n"
- (int) strlen(form), form);
- gg_debug(GG_DEBUG_MISC, "=> register, not enough memory for query\n");
- if (!(h = gg_http_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, async,
- "POST", "/appsvc/fmregister3.asp", query)))
- gg_debug(GG_DEBUG_MISC, "=> register, gg_http_connect() failed mysteriously\n");
- h->type = GG_SESSION_REGISTER;
- h->callback = gg_pubdir_watch_fd;
- h->destroy = gg_pubdir_free;
- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
- * Operacja będzie zakończona, gdy pole \c state będzie równe \c GG_STATE_DONE.
- * Jeśli wystąpi błąd, \c state będzie równe \c GG_STATE_ERROR, a kod błędu
- * znajdzie się w polu \c error.
- * \note W rzeczywistości funkcja jest makrem rozwijanym do
- * \c gg_pubdir_watch_fd().
- * \param h Struktura połączenia
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_register_watch_fd(struct gg_httpd *h)
- return gg_pubdir_watch_fd(h);
- * Zwalnia zasoby po operacji.
- * \note W rzeczywistości funkcja jest makrem rozwijanym do \c gg_pubdir_free().
- * \param h Struktura połączenia
-void gg_register_free(struct gg_http *h)
- return gg_pubdir_free(h);
- * Wymaga wcześniejszego pobrania tokenu za pomocą \c gg_token().
- * \param uin Numer Gadu-Gadu
- * \param password Hasło
- * \param tokenid Identyfikator tokenu
- * \param tokenval Zawartość tokenu
- * \param async Flaga połączenia asynchronicznego
- * \return Struktura \c gg_http lub \c NULL w przypadku błędu
-struct gg_http *gg_unregister3(uin_t uin, const char *password, const char *tokenid, const char *tokenval, int async)
- char *__fmpwd, *__pwd, *__tokenid, *__tokenval, *form, *query;
- if (!password || !tokenid || !tokenval) {
- gg_debug(GG_DEBUG_MISC, "=> unregister, NULL parameter\n");
- __pwd = gg_saprintf("%d", rand());
- __fmpwd = gg_urlencode(password);
- __tokenid = gg_urlencode(tokenid);
- __tokenval = gg_urlencode(tokenval);
- if (!__fmpwd || !__pwd || !__tokenid || !__tokenval) {
- gg_debug(GG_DEBUG_MISC, "=> unregister, not enough memory for form fields\n");
- form = gg_saprintf("fmnumber=%d&fmpwd=%s&delete=1&pwd=%s&"
- "email=deletedaccount@gadu-gadu.pl&tokenid=%s&tokenval=%s&"
- "code=%u", uin, __fmpwd, __pwd, __tokenid, __tokenval,
- gg_http_hash("ss", "deletedaccount@gadu-gadu.pl", __pwd));
- gg_debug(GG_DEBUG_MISC, "=> unregister, not enough memory for form query\n");
- gg_debug(GG_DEBUG_MISC, "=> unregister, %s\n", form);
- "Host: " GG_REGISTER_HOST "\r\n"
- "Content-Type: application/x-www-form-urlencoded\r\n"
- "User-Agent: " GG_HTTP_USERAGENT "\r\n"
- "Content-Length: %d\r\n"
- (int) strlen(form), form);
- gg_debug(GG_DEBUG_MISC, "=> unregister, not enough memory for query\n");
- if (!(h = gg_http_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, async,
- "POST", "/appsvc/fmregister3.asp", query)))
- gg_debug(GG_DEBUG_MISC, "=> unregister, gg_http_connect() failed mysteriously\n");
- h->type = GG_SESSION_UNREGISTER;
- h->callback = gg_pubdir_watch_fd;
- h->destroy = gg_pubdir_free;
- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
- * Operacja będzie zakończona, gdy pole \c state będzie równe \c GG_STATE_DONE.
- * Jeśli wystąpi błąd, \c state będzie równe \c GG_STATE_ERROR, a kod błędu
- * znajdzie się w polu \c error.
- * \note W rzeczywistości funkcja jest makrem rozwijanym do
- * \c gg_pubdir_watch_fd().
- * \param h Struktura połączenia
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_unregister_watch_fd(struct gg_httpd *h)
- return gg_pubdir_watch_fd(h);
- * Zwalnia zasoby po operacji.
- * \note W rzeczywistości funkcja jest makrem rozwijanym do \c gg_pubdir_free().
- * \param h Struktura połączenia
-void gg_unregister_free(struct gg_http *h)
- return gg_pubdir_free(h);
- * Zmienia hasło użytkownika.
- * Wymaga wcześniejszego pobrania tokenu za pomocą \c gg_token().
- * \param uin Numer Gadu-Gadu
- * \param email Adres e-mail
- * \param passwd Obecne hasło
- * \param newpasswd Nowe hasło
- * \param tokenid Identyfikator tokenu
- * \param tokenval Zawartość tokenu
- * \param async Flaga połączenia asynchronicznego
- * \return Struktura \c gg_http lub \c NULL w przypadku błędu
-struct gg_http *gg_change_passwd4(uin_t uin, const char *email,
- const char *passwd, const char *newpasswd, const char *tokenid,
- const char *tokenval, int async)
- char *form, *query, *__email, *__fmpwd, *__pwd, *__tokenid, *__tokenval;
- if (!uin || !email || !passwd || !newpasswd || !tokenid || !tokenval) {
- gg_debug(GG_DEBUG_MISC, "=> change, NULL parameter\n");
- __fmpwd = gg_urlencode(passwd);
- __pwd = gg_urlencode(newpasswd);
- __email = gg_urlencode(email);
- __tokenid = gg_urlencode(tokenid);
- __tokenval = gg_urlencode(tokenval);
- if (!__fmpwd || !__pwd || !__email || !__tokenid || !__tokenval) {
- gg_debug(GG_DEBUG_MISC, "=> change, not enough memory for form fields\n");
- if (!(form = gg_saprintf("fmnumber=%d&fmpwd=%s&pwd=%s&email=%s&"
- "tokenid=%s&tokenval=%s&code=%u", uin, __fmpwd, __pwd, __email,
- __tokenid, __tokenval, gg_http_hash("ss", email, newpasswd))))
- gg_debug(GG_DEBUG_MISC, "=> change, not enough memory for form fields\n");
- gg_debug(GG_DEBUG_MISC, "=> change, %s\n", form);
- "Host: " GG_REGISTER_HOST "\r\n"
- "Content-Type: application/x-www-form-urlencoded\r\n"
- "User-Agent: " GG_HTTP_USERAGENT "\r\n"
- "Content-Length: %d\r\n"
- (int) strlen(form), form);
- gg_debug(GG_DEBUG_MISC, "=> change, not enough memory for query\n");
- if (!(h = gg_http_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, async,
- "POST", "/appsvc/fmregister3.asp", query)))
- gg_debug(GG_DEBUG_MISC, "=> change, gg_http_connect() failed mysteriously\n");
- h->type = GG_SESSION_PASSWD;
- h->callback = gg_pubdir_watch_fd;
- h->destroy = gg_pubdir_free;
- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
- * Operacja będzie zakończona, gdy pole \c state będzie równe \c GG_STATE_DONE.
- * Jeśli wystąpi błąd, \c state będzie równe \c GG_STATE_ERROR, a kod błędu
- * znajdzie się w polu \c error.
- * \note W rzeczywistości funkcja jest makrem rozwijanym do
- * \c gg_pubdir_watch_fd().
- * \param h Struktura połączenia
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_change_passwd_watch_fd(struct gg_httpd *h)
- return gg_pubdir_watch_fd(h);
- * Zwalnia zasoby po operacji.
- * \note W rzeczywistości funkcja jest makrem rozwijanym do \c gg_pubdir_free().
- * \param h Struktura połączenia
-void gg_change_passwd_free(struct gg_http *h)
- return gg_pubdir_free(h);
- * Wysyła hasło użytkownika na e-mail.
- * Wymaga wcześniejszego pobrania tokenu za pomocą \c gg_token().
- * \param uin Numer Gadu-Gadu
- * \param email Adres e-mail (podany przy rejestracji)
- * \param tokenid Identyfikator tokenu
- * \param tokenval Zawartość tokenu
- * \param async Flaga połączenia asynchronicznego
- * \return Struktura \c gg_http lub \c NULL w przypadku błędu
-struct gg_http *gg_remind_passwd3(uin_t uin, const char *email, const char *tokenid, const char *tokenval, int async)
- char *form, *query, *__tokenid, *__tokenval, *__email;
- if (!tokenid || !tokenval || !email) {
- gg_debug(GG_DEBUG_MISC, "=> remind, NULL parameter\n");
- __tokenid = gg_urlencode(tokenid);
- __tokenval = gg_urlencode(tokenval);
- __email = gg_urlencode(email);
- if (!__tokenid || !__tokenval || !__email) {
- gg_debug(GG_DEBUG_MISC, "=> remind, not enough memory for form fields\n");
- if (!(form = gg_saprintf("userid=%d&code=%u&tokenid=%s&tokenval=%s&"
- "email=%s", uin, gg_http_hash("u", uin), __tokenid, __tokenval,
- gg_debug(GG_DEBUG_MISC, "=> remind, not enough memory for form fields\n");
- gg_debug(GG_DEBUG_MISC, "=> remind, %s\n", form);
- "Host: " GG_REMIND_HOST "\r\n"
- "Content-Type: application/x-www-form-urlencoded\r\n"
- "User-Agent: " GG_HTTP_USERAGENT "\r\n"
- "Content-Length: %d\r\n"
- (int) strlen(form), form);
- gg_debug(GG_DEBUG_MISC, "=> remind, not enough memory for query\n");
- if (!(h = gg_http_connect(GG_REMIND_HOST, GG_REMIND_PORT, async, "POST", "/appsvc/fmsendpwd3.asp", query))) {
- gg_debug(GG_DEBUG_MISC, "=> remind, gg_http_connect() failed mysteriously\n");
- h->type = GG_SESSION_REMIND;
- h->callback = gg_pubdir_watch_fd;
- h->destroy = gg_pubdir_free;
- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
- * Operacja będzie zakończona, gdy pole \c state będzie równe \c GG_STATE_DONE.
- * Jeśli wystąpi błąd, \c state będzie równe \c GG_STATE_ERROR, a kod błędu
- * znajdzie się w polu \c error.
- * \note W rzeczywistości funkcja jest makrem rozwijanym do
- * \c gg_pubdir_watch_fd().
- * \param h Struktura połączenia
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_remind_watch_fd(struct gg_httpd *h)
- return gg_pubdir_watch_fd(h);
- * Zwalnia zasoby po operacji.
- * \note W rzeczywistości funkcja jest makrem rozwijanym do \c gg_pubdir_free().
- * \param h Struktura połączenia
-void gg_remind_free(struct gg_http *h)
- return gg_pubdir_free(h);
- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
- * Operacja będzie zakończona, gdy pole \c state będzie równe \c GG_STATE_DONE.
- * Jeśli wystąpi błąd, \c state będzie równe \c GG_STATE_ERROR, a kod błędu
- * znajdzie się w polu \c error.
- * \param h Struktura połączenia
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_pubdir_watch_fd(struct gg_http *h)
- if (h->state == GG_STATE_ERROR) {
- gg_debug(GG_DEBUG_MISC, "=> pubdir, watch_fd issued on failed session\n");
- if (h->state != GG_STATE_PARSING) {
- if (gg_http_watch_fd(h) == -1) {
- gg_debug(GG_DEBUG_MISC, "=> pubdir, http failure\n");
- if (h->state != GG_STATE_PARSING)
- h->state = GG_STATE_DONE;
- if (!(h->data = p = malloc(sizeof(struct gg_pubdir)))) {
- gg_debug(GG_DEBUG_MISC, "=> pubdir, not enough memory for results\n");
- gg_debug(GG_DEBUG_MISC, "=> pubdir, let's parse \"%s\"\n", h->body);
- if ((tmp = strstr(h->body, "Tokens okregisterreply_packet.reg.dwUserId="))) {
- p->uin = strtol(tmp + sizeof("Tokens okregisterreply_packet.reg.dwUserId=") - 1, NULL, 0);
- p->error = GG_PUBDIR_ERROR_NONE;
- gg_debug(GG_DEBUG_MISC, "=> pubdir, success (okregisterreply, uin=%d)\n", p->uin);
- } else if ((tmp = strstr(h->body, "success")) || (tmp = strstr(h->body, "results"))) {
- p->uin = strtol(tmp + 8, NULL, 0);
- p->error = GG_PUBDIR_ERROR_NONE;
- gg_debug(GG_DEBUG_MISC, "=> pubdir, success (uin=%d)\n", p->uin);
- } else if (strncmp(h->body, "error1", 6) == 0 || strncmp(h->body, "error3", 6) == 0) {
- p->error = GG_PUBDIR_ERROR_NEW_PASSWORD;
- gg_debug(GG_DEBUG_MISC, "=> pubdir, invalid new password\n");
- } else if (strncmp(h->body, "not authenticated", 17) == 0) {
- p->error = GG_PUBDIR_ERROR_OLD_PASSWORD;
- gg_debug(GG_DEBUG_MISC, "=> pubdir, invalid old password\n");
- } else if (strncmp(h->body, "bad_tokenval", 12) == 0) {
- p->error = GG_PUBDIR_ERROR_TOKEN;
- gg_debug(GG_DEBUG_MISC, "=> pubdir, invalid token\n");
- p->error = GG_PUBDIR_ERROR_OTHER;
- gg_debug(GG_DEBUG_MISC, "=> pubdir, unknown error\n");
- * Zwalnia zasoby po operacji na katalogu publicznym.
- * \param h Struktura połączenia
-void gg_pubdir_free(struct gg_http *h)
- * Pobiera token do autoryzacji operacji na katalogu publicznym.
- * Token jest niezbędny do tworzenia nowego i usuwania użytkownika,
- * \param async Flaga połączenia asynchronicznego
- * \return Struktura \c gg_http lub \c NULL w przypadku błędu
-struct gg_http *gg_token(int async)
- query = "Host: " GG_REGISTER_HOST "\r\n"
- "Content-Type: application/x-www-form-urlencoded\r\n"
- "User-Agent: " GG_HTTP_USERAGENT "\r\n"
- "Content-Length: 0\r\n"
- if (!(h = gg_http_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, async, "POST", "/appsvc/regtoken.asp", query))) {
- gg_debug(GG_DEBUG_MISC, "=> token, gg_http_connect() failed mysteriously\n");
- h->type = GG_SESSION_TOKEN;
- h->callback = gg_token_watch_fd;
- h->destroy = gg_token_free;
- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
- * Operacja będzie zakończona, gdy pole \c state będzie równe \c GG_STATE_DONE.
- * Jeśli wystąpi błąd, \c state będzie równe \c GG_STATE_ERROR, a kod błędu
- * znajdzie się w polu \c error.
- * \param h Struktura połączenia
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_token_watch_fd(struct gg_http *h)
- if (h->state == GG_STATE_ERROR) {
- gg_debug(GG_DEBUG_MISC, "=> token, watch_fd issued on failed session\n");
- if (h->state != GG_STATE_PARSING) {
- if (gg_http_watch_fd(h) == -1) {
- gg_debug(GG_DEBUG_MISC, "=> token, http failure\n");
- if (h->state != GG_STATE_PARSING)
- /* jeśli h->data jest puste, to ściągaliśmy tokenid i url do niego,
- * ale jeśli coś tam jest, to znaczy, że mamy drugi etap polegający
- * na pobieraniu tokenu. */
- int width, height, length;
- char *url = NULL, *tokenid = NULL, *path, *headers;
- gg_debug(GG_DEBUG_MISC, "=> token body \"%s\"\n", h->body);
- results_len = h->body ? strlen(h->body) : 0;
- if (h->body && (!(url = malloc(results_len)) || !(tokenid = malloc(results_len)))) {
- gg_debug(GG_DEBUG_MISC, "=> token, not enough memory for results\n");
- if (!h->body || sscanf(h->body, "%d %d %d\r\n%s\r\n%s", &width, &height, &length, tokenid, url) != 5) {
- gg_debug(GG_DEBUG_MISC, "=> token, parsing failed\n");
- /* dostaliśmy tokenid i wszystkie niezbędne informacje,
- * więc pobierzmy obrazek z tokenem */
- if (strncmp(url, "http://", 7)) {
- path = gg_saprintf("%s?tokenid=%s", url, tokenid);
- host = GG_REGISTER_HOST;
- char *slash = strchr(url + 7, '/');
- path = gg_saprintf("%s?tokenid=%s", slash, tokenid);
- gg_debug(GG_DEBUG_MISC, "=> token, url parsing failed\n");
- gg_debug(GG_DEBUG_MISC, "=> token, not enough memory for token url\n");
- if (!(headers = gg_saprintf("Host: %s\r\nUser-Agent: " GG_HTTP_USERAGENT "\r\n\r\n", host))) {
- gg_debug(GG_DEBUG_MISC, "=> token, not enough memory for token url\n");
- if (!(h2 = gg_http_connect(host, GG_REGISTER_PORT, h->async, "GET", path, headers))) {
- gg_debug(GG_DEBUG_MISC, "=> token, gg_http_connect() failed mysteriously\n");
- gg_http_free_fields(h);
- memcpy(h, h2, sizeof(struct gg_http));
- h->type = GG_SESSION_TOKEN;
- h->callback = gg_token_watch_fd;
- h->destroy = gg_token_free;
- if (!(h->data = t = malloc(sizeof(struct gg_token)))) {
- gg_debug(GG_DEBUG_MISC, "=> token, not enough memory for token data\n");
- /* obrazek mamy w h->body */
- h->state = GG_STATE_DONE;
- * Zwalnia zasoby po operacji pobierania tokenu.
- * \param h Struktura połączenia
-void gg_token_free(struct gg_http *h)
- * c-indentation-style: k&r
- * indent-tabs-mode: notnil
--- a/libpurple/protocols/gg/lib/pubdir50.c Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,555 +0,0 @@
- * (C) Copyright 2003 Wojtek Kaniewski <wojtekka@irc.pl>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
- * \brief Obsługa katalogu publicznego od wersji Gadu-Gadu 5.x
- * \todo Zoptymalizować konwersję CP1250<->UTF8. Obecnie robiona jest
- * testowa konwersja, żeby poznać długość tekstu wynikowego.
- * Tworzy nowe zapytanie katalogu publicznego.
- * \param type Rodzaj zapytania
- * \return Zmienna \c gg_pubdir50_t lub \c NULL w przypadku błędu.
-gg_pubdir50_t gg_pubdir50_new(int type)
- gg_pubdir50_t res = malloc(sizeof(struct gg_pubdir50_s));
- gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50_new(%d);\n", type);
- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_new() out of memory\n");
- memset(res, 0, sizeof(struct gg_pubdir50_s));
- * \internal Dodaje lub zastępuje pole zapytania lub odpowiedzi katalogu
- * \param req Zapytanie lub odpowiedź
- * \param num Numer wyniku odpowiedzi (0 dla zapytania)
- * \param field Nazwa pola
- * \param value Wartość pola
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-static int gg_pubdir50_add_n(gg_pubdir50_t req, int num, const char *field, const char *value)
- struct gg_pubdir50_entry *tmp = NULL, *entry;
- char *dupfield, *dupvalue;
- gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50_add_n(%p, %d, \"%s\", \"%s\");\n", req, num, field, value);
- if (!(dupvalue = strdup(value))) {
- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_add_n() out of memory\n");
- for (i = 0; i < req->entries_count; i++) {
- if (req->entries[i].num != num || strcmp(req->entries[i].field, field))
- free(req->entries[i].value);
- req->entries[i].value = dupvalue;
- if (!(dupfield = strdup(field))) {
- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_add_n() out of memory\n");
- if (!(tmp = realloc(req->entries, sizeof(struct gg_pubdir50_entry) * (req->entries_count + 1)))) {
- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_add_n() out of memory\n");
- entry = &req->entries[req->entries_count];
- entry->field = dupfield;
- entry->value = dupvalue;
- * Dodaje pole zapytania.
- * \param field Nazwa pola
- * \param value Wartość pola
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_pubdir50_add(gg_pubdir50_t req, const char *field, const char *value)
- return gg_pubdir50_add_n(req, 0, field, value);
- * Ustawia numer sekwencyjny zapytania.
- * \param seq Numer sekwencyjny
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_pubdir50_seq_set(gg_pubdir50_t req, uint32_t seq)
- gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50_seq_set(%p, %d);\n", req, seq);
- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_seq_set() invalid arguments\n");
- * Zwalnia zasoby po zapytaniu lub odpowiedzi katalogu publicznego.
- * \param s Zapytanie lub odpowiedź
-void gg_pubdir50_free(gg_pubdir50_t s)
- for (i = 0; i < s->entries_count; i++) {
- free(s->entries[i].field);
- free(s->entries[i].value);
- * Wysyła zapytanie katalogu publicznego do serwera.
- * \param sess Struktura sesji
- * \return Numer sekwencyjny zapytania lub 0 w przypadku błędu
-uint32_t gg_pubdir50(struct gg_session *sess, gg_pubdir50_t req)
- struct gg_pubdir50_request *r;
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_pubdir50(%p, %p);\n", sess, req);
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_pubdir50() invalid arguments\n");
- if (sess->state != GG_STATE_CONNECTED) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_pubdir50() not connected\n");
- for (i = 0; i < req->entries_count; i++) {
- /* wyszukiwanie bierze tylko pierwszy wpis */
- if (req->entries[i].num)
- if (sess->encoding == GG_ENCODING_CP1250) {
- size += strlen(req->entries[i].field) + 1;
- size += strlen(req->entries[i].value) + 1;
- /* XXX \todo zoptymalizować */
- tmp = gg_encoding_convert(req->entries[i].field, sess->encoding, GG_ENCODING_CP1250, -1, -1);
- size += strlen(tmp) + 1;
- /* XXX \todo zoptymalizować */
- tmp = gg_encoding_convert(req->entries[i].value, sess->encoding, GG_ENCODING_CP1250, -1, -1);
- size += strlen(tmp) + 1;
- if (!(buf = malloc(size))) {
- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_pubdir50() out of memory (%d bytes)\n", size);
- r = (struct gg_pubdir50_request*) buf;
- r->seq = gg_fix32(req->seq);
- for (i = 0, p = buf + 5; i < req->entries_count; i++) {
- if (req->entries[i].num)
- if (sess->encoding == GG_ENCODING_CP1250) {
- strcpy(p, req->entries[i].field);
- strcpy(p, req->entries[i].value);
- /* XXX \todo zoptymalizować */
- tmp = gg_encoding_convert(req->entries[i].field, sess->encoding, GG_ENCODING_CP1250, -1, -1);
- /* XXX \todo zoptymalizować */
- tmp = gg_encoding_convert(req->entries[i].value, sess->encoding, GG_ENCODING_CP1250, -1, -1);
- if (gg_send_packet(sess, GG_PUBDIR50_REQUEST, buf, size, NULL, 0) == -1)
- * \internal Analizuje przychodzący pakiet odpowiedzi i zapisuje wynik
- * w strukturze \c gg_event.
- * \param sess Struktura sesji
- * \param e Struktura zdarzenia
- * \param packet Pakiet odpowiedzi
- * \param length Długość pakietu odpowiedzi
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_pubdir50_handle_reply_sess(struct gg_session *sess, struct gg_event *e, const char *packet, int length)
- const char *end = packet + length, *p;
- const struct gg_pubdir50_reply *r = (const struct gg_pubdir50_reply*) packet;
- gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50_handle_reply_sess(%p, %p, %p, %d);\n", sess, e, packet, length);
- if (!sess || !e || !packet) {
- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_handle_reply() invalid arguments\n");
- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_handle_reply() packet too short\n");
- if (!(res = gg_pubdir50_new(r->type))) {
- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_handle_reply() unable to allocate reply\n");
- e->event.pubdir50 = res;
- res->seq = gg_fix32(r->seq);
- e->type = GG_EVENT_PUBDIR50_READ;
- case GG_PUBDIR50_WRITE:
- e->type = GG_EVENT_PUBDIR50_WRITE;
- e->type = GG_EVENT_PUBDIR50_SEARCH_REPLY;
- /* pomiń początek odpowiedzi */
- const char *field, *value;
- /* sprawdź, czy nie mamy podziału na kolejne pole */
- for (p = field; p < end; p++) {
- /* jeśli mamy koniec tekstu... */
- /* ...i jeszcze nie mieliśmy wartości pola to
- * wiemy, że po tym zerze jest wartość... */
- /* ...w przeciwym wypadku koniec
- * wartości i możemy wychodzić
- /* sprawdźmy, czy pole nie wychodzi poza pakiet, żeby nie
- * mieć segfaultów, jeśli serwer przestanie zakańczać pakietów
- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_handle_reply() premature end of packet\n");
- /* jeśli dostaliśmy namier na następne wyniki, to znaczy że
- * mamy koniec wyników i nie jest to kolejna osoba. */
- if (!strcasecmp(field, "nextstart")) {
- res->next = value ? atoi(value) : 0;
- if (sess->encoding == GG_ENCODING_CP1250) {
- if (gg_pubdir50_add_n(res, num, field, value) == -1)
- tmp = gg_encoding_convert(value, GG_ENCODING_CP1250, sess->encoding, -1, -1);
- if (gg_pubdir50_add_n(res, num, field, tmp) == -1) {
- * Pobiera pole z odpowiedzi katalogu publicznego.
- * \param num Numer wyniku odpowiedzi
- * \param field Nazwa pola (wielkość liter nie ma znaczenia)
- * \return Wartość pola lub \c NULL jeśli nie znaleziono
-const char *gg_pubdir50_get(gg_pubdir50_t res, int num, const char *field)
- gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50_get(%p, %d, \"%s\");\n", res, num, field);
- if (!res || num < 0 || !field) {
- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_get() invalid arguments\n");
- for (i = 0; i < res->entries_count; i++) {
- if (res->entries[i].num == num && !strcasecmp(res->entries[i].field, field)) {
- value = res->entries[i].value;
- * Zwraca liczbę wyników odpowiedzi.
- * \return Liczba wyników lub -1 w przypadku błędu
-int gg_pubdir50_count(gg_pubdir50_t res)
- return (!res) ? -1 : res->count;
- * Zwraca rodzaj zapytania lub odpowiedzi.
- * \param res Zapytanie lub odpowiedź
- * \return Rodzaj lub -1 w przypadku błędu
-int gg_pubdir50_type(gg_pubdir50_t res)
- return (!res) ? -1 : res->type;
- * Zwraca numer, od którego należy rozpocząc kolejne wyszukiwanie.
- * Dłuższe odpowiedzi katalogu publicznego są wysyłane przez serwer
- * w mniejszych paczkach. Po otrzymaniu odpowiedzi, jeśli numer kolejnego
- * wyszukiwania jest większy od zera, dalsze wyniki można otrzymać przez
- * wywołanie kolejnego zapytania z określonym numerem początkowym.
- * \return Numer lub -1 w przypadku błędu
-uin_t gg_pubdir50_next(gg_pubdir50_t res)
- return (!res) ? (unsigned) -1 : res->next;
- * Zwraca numer sekwencyjny zapytania lub odpowiedzi.
- * \param res Zapytanie lub odpowiedź
- * \return Numer sekwencyjny lub -1 w przypadku błędu
-uint32_t gg_pubdir50_seq(gg_pubdir50_t res)
- return (!res) ? (unsigned) -1 : res->seq;
- * c-indentation-style: k&r
- * indent-tabs-mode: notnil
--- a/libpurple/protocols/gg/lib/resolver.c Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1132 +0,0 @@
- * (C) Copyright 2001-2009 Wojtek Kaniewski <wojtekka@irc.pl>
- * Robert J. Woźny <speedy@ziew.org>
- * Arkadiusz Miśkiewicz <arekm@pld-linux.org>
- * Tomasz Chiliński <chilek@chilan.com>
- * Adam Wysocki <gophi@ekg.chmurka.net>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
- * \brief Funkcje rozwiązywania nazw
-#ifdef GG_CONFIG_HAVE_FORK
-/** Sposób rozwiązywania nazw serwerów */
-static gg_resolver_t gg_global_resolver_type = GG_RESOLVER_DEFAULT;
-/** Funkcja rozpoczynająca rozwiązywanie nazwy */
-static int (*gg_global_resolver_start)(int *fd, void **private_data, const char *hostname);
-/** Funkcja zwalniająca zasoby po rozwiązaniu nazwy */
-static void (*gg_global_resolver_cleanup)(void **private_data, int force);
-#ifdef GG_CONFIG_HAVE_PTHREAD
- * \internal Funkcja pomocnicza zwalniająca zasoby po rozwiązywaniu nazwy
- * \note Funkcja nie powinna być statyczna, ponieważ zostanie potraktowana
- * jako inline i kompilator może "zoptymalizować" jej wywołanie w funkcji
- * pthread_cleanup_pop().
- * \param data Wskaźnik na wskaźnik bufora zaalokowanego w wątku
-void gg_resolver_cleaner(void *data)
- void **buf_ptr = (void **) data;
-#endif /* GG_CONFIG_HAVE_PTHREAD */
- * \internal Odpowiednik \c gethostbyname zapewniający współbieżność.
- * Jeśli dany system dostarcza \c gethostbyname_r, używa się tej wersji, jeśli
- * nie, to zwykłej \c gethostbyname. Wynikiem jest tablica adresów zakończona
- * wartością INADDR_NONE, którą należy zwolnić po użyciu.
- * \param hostname Nazwa serwera
- * \param result Wskaźnik na wskaźnik z tablicą adresów zakończoną INADDR_NONE
- * \param count Wskaźnik na zmienną, do ktorej zapisze się liczbę wyników
- * \param pthread Flaga blokowania unicestwiania wątku podczas alokacji pamięci
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_gethostbyname_real(const char *hostname, struct in_addr **result, unsigned int *count, int pthread)
-#ifdef GG_CONFIG_HAVE_GETHOSTBYNAME_R
- struct hostent *he_ptr = NULL;
-#ifdef GG_CONFIG_HAVE_PTHREAD
-#ifdef GG_CONFIG_HAVE_PTHREAD
- pthread_cleanup_push(gg_resolver_cleaner, &buf);
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);
-#ifdef GG_CONFIG_HAVE_PTHREAD
- pthread_setcancelstate(old_state, NULL);
- ret = gethostbyname_r(hostname, &he, buf, buf_len, &he_ptr, &h_errnop);
- he_ptr = gethostbyname_r(hostname, &he, buf, buf_len, &h_errnop);
- if (he_ptr != NULL || errno != ERANGE)
-#ifdef GG_CONFIG_HAVE_PTHREAD
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);
- new_buf = realloc(buf, buf_len);
-#ifdef GG_CONFIG_HAVE_PTHREAD
- pthread_setcancelstate(old_state, NULL);
- if (ret == 0 && he_ptr != NULL && he_ptr->h_addr_list[0] != NULL) {
- /* Policz liczbę adresów */
- for (i = 0; he_ptr->h_addr_list[i] != NULL; i++);
-#ifdef GG_CONFIG_HAVE_PTHREAD
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);
- *result = malloc((i + 1) * sizeof(struct in_addr));
-#ifdef GG_CONFIG_HAVE_PTHREAD
- pthread_setcancelstate(old_state, NULL);
- for (i = 0; he_ptr->h_addr_list[i] != NULL; i++)
- memcpy(&((*result)[i]), he_ptr->h_addr_list[i], sizeof(struct in_addr));
- (*result)[i].s_addr = INADDR_NONE;
-#ifdef GG_CONFIG_HAVE_PTHREAD
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);
-#ifdef GG_CONFIG_HAVE_PTHREAD
- pthread_setcancelstate(old_state, NULL);
-#ifdef GG_CONFIG_HAVE_PTHREAD
- pthread_cleanup_pop(0);
-#else /* GG_CONFIG_HAVE_GETHOSTBYNAME_R */
-#ifdef GG_CONFIG_HAVE_PTHREAD
- if (result == NULL || count == NULL) {
- he = gethostbyname(hostname);
- if (he == NULL || he->h_addr_list[0] == NULL)
- /* Policz liczbę adresów */
- for (i = 0; he->h_addr_list[i] != NULL; i++);
-#ifdef GG_CONFIG_HAVE_PTHREAD
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);
- *result = malloc((i + 1) * sizeof(struct in_addr));
-#ifdef GG_CONFIG_HAVE_PTHREAD
- pthread_setcancelstate(old_state, NULL);
- for (i = 0; he->h_addr_list[i] != NULL; i++)
- memcpy(&((*result)[i]), he->h_addr_list[i], sizeof(struct in_addr));
- (*result)[i].s_addr = INADDR_NONE;
-#endif /* GG_CONFIG_HAVE_GETHOSTBYNAME_R */
- * \internal Rozwiązuje nazwę i zapisuje wynik do podanego gniazda.
- * \note Użycie logowania w tej funkcji może mieć negatywny wpływ na
- * aplikacje jednowątkowe korzystające.
- * \param fd Deskryptor gniazda
- * \param hostname Nazwa serwera
- * \param pthread Flaga blokowania unicestwiania wątku podczas alokacji pamięci
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-static int gg_resolver_run(int fd, const char *hostname, int pthread)
- struct in_addr addr_ip[2], *addr_list = NULL;
- unsigned int addr_count;
-#ifdef GG_CONFIG_HAVE_PTHREAD
-#ifdef GG_CONFIG_HAVE_PTHREAD
- pthread_cleanup_push(gg_resolver_cleaner, &addr_list);
- if ((addr_ip[0].s_addr = inet_addr(hostname)) == INADDR_NONE) {
- if (gg_gethostbyname_real(hostname, &addr_list, &addr_count, pthread) == -1) {
-#ifdef GG_CONFIG_HAVE_PTHREAD
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);
-#ifdef GG_CONFIG_HAVE_PTHREAD
- pthread_setcancelstate(old_state, NULL);
- /* addr_ip[0] już zawiera INADDR_NONE */
- addr_ip[1].s_addr = INADDR_NONE;
- if (send(fd, addr_list != NULL ? addr_list : addr_ip,
- (addr_count + 1) * sizeof(struct in_addr), 0) !=
- (int)((addr_count + 1) * sizeof(struct in_addr)))
-#ifdef GG_CONFIG_HAVE_PTHREAD
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);
-#ifdef GG_CONFIG_HAVE_PTHREAD
- pthread_setcancelstate(old_state, NULL);
- pthread_cleanup_pop(0);
- * \internal Odpowiednik \c gethostbyname zapewniający współbieżność.
- * Jeśli dany system dostarcza \c gethostbyname_r, używa się tej wersji, jeśli
- * nie, to zwykłej \c gethostbyname. Funkcja służy do zachowania zgodności
- * ABI i służy do pobierania tylko pierwszego adresu -- pozostałe mogą
- * zostać zignorowane przez aplikację.
- * \param hostname Nazwa serwera
- * \return Zaalokowana struktura \c in_addr lub NULL w przypadku błędu.
-struct in_addr *gg_gethostbyname(const char *hostname)
- struct in_addr *result;
- if (gg_gethostbyname_real(hostname, &result, &count, 0) == -1)
-#ifdef GG_CONFIG_HAVE_FORK
- * \internal Struktura przekazywana do wątku rozwiązującego nazwę.
-struct gg_resolver_fork_data {
- int pid; /*< Identyfikator procesu */
- * \internal Rozwiązuje nazwę serwera w osobnym procesie.
- * Połączenia asynchroniczne nie mogą blokować procesu w trakcie rozwiązywania
- * nazwy serwera. W tym celu tworzona jest para gniazd, nowy proces i dopiero
- * w nim przeprowadzane jest rozwiązywanie nazwy. Deskryptor gniazda do odczytu
- * zapisuje się w strukturze sieci i czeka na dane w postaci struktury
- * \c in_addr. Jeśli nie znaleziono nazwy, zwracana jest \c INADDR_NONE.
- * \param fd Wskaźnik na zmienną, gdzie zostanie umieszczony deskryptor gniazda
- * \param priv_data Wskaźnik na zmienną, gdzie zostanie umieszczony wskaźnik
- * do numeru procesu potomnego rozwiązującego nazwę
- * \param hostname Nazwa serwera do rozwiązania
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-static int gg_resolver_fork_start(int *fd, void **priv_data, const char *hostname)
- struct gg_resolver_fork_data *data = NULL;
- int pipes[2], new_errno;
- gg_debug(GG_DEBUG_FUNCTION, "** gg_resolver_fork_start(%p, %p, \"%s\");\n", fd, priv_data, hostname);
- if (fd == NULL || priv_data == NULL || hostname == NULL) {
- gg_debug(GG_DEBUG_MISC, "// gg_resolver_fork_start() invalid arguments\n");
- data = malloc(sizeof(struct gg_resolver_fork_data));
- gg_debug(GG_DEBUG_MISC, "// gg_resolver_fork_start() out of memory for resolver data\n");
- if (socketpair(AF_LOCAL, SOCK_STREAM, 0, pipes) == -1) {
- gg_debug(GG_DEBUG_MISC, "// gg_resolver_fork_start() unable "
- "to create pipes (errno=%d, %s)\n",
- errno, strerror(errno));
- status = (gg_resolver_run(pipes[1], hostname, 0) == -1) ? 1 : 0;
- gg_debug(GG_DEBUG_MISC, "// gg_resolver_fork_start() %p\n", data);
- * \internal Usuwanie zasobów po procesie rozwiązywaniu nazwy.
- * Funkcja wywoływana po zakończeniu rozwiązanywania nazwy lub przy zwalnianiu
- * zasobów sesji podczas rozwiązywania nazwy.
- * \param priv_data Wskaźnik na zmienną przechowującą wskaźnik do prywatnych
- * \param force Flaga usuwania zasobów przed zakończeniem działania
-static void gg_resolver_fork_cleanup(void **priv_data, int force)
- struct gg_resolver_fork_data *data;
- if (priv_data == NULL || *priv_data == NULL)
- data = (struct gg_resolver_fork_data*) *priv_data;
- kill(data->pid, SIGKILL);
- /* we don't care about child's exit status, just want to clean it up */
- (void)waitpid(data->pid, NULL, WNOHANG);
-#endif /* GG_CONFIG_HAVE_FORK */
-#ifdef GG_CONFIG_HAVE_PTHREAD
- * \internal Struktura przekazywana do wątku rozwiązującego nazwę.
-struct gg_resolver_pthread_data {
- pthread_t thread; /*< Identyfikator wątku */
- char *hostname; /*< Nazwa serwera */
- int wfd; /*< Deskryptor do zapisu */
- * \internal Usuwanie zasobów po wątku rozwiązywaniu nazwy.
- * Funkcja wywoływana po zakończeniu rozwiązanywania nazwy lub przy zwalnianiu
- * zasobów sesji podczas rozwiązywania nazwy.
- * \param priv_data Wskaźnik na zmienną przechowującą wskaźnik do prywatnych
- * \param force Flaga usuwania zasobów przed zakończeniem działania
-static void gg_resolver_pthread_cleanup(void **priv_data, int force)
- struct gg_resolver_pthread_data *data;
- if (priv_data == NULL || *priv_data == NULL)
- data = (struct gg_resolver_pthread_data *) *priv_data;
- pthread_cancel(data->thread);
- pthread_join(data->thread, NULL);
- * \internal Wątek rozwiązujący nazwę.
- * \param arg Wskaźnik na strukturę \c gg_resolver_pthread_data
-static void *gg_resolver_pthread_thread(void *arg)
- struct gg_resolver_pthread_data *data = arg;
- if (gg_resolver_run(data->wfd, data->hostname, 1) == -1)
- pthread_exit((void*) -1);
- return NULL; /* żeby kompilator nie marudził */
- * \internal Rozwiązuje nazwę serwera w osobnym wątku.
- * Funkcja działa analogicznie do \c gg_resolver_fork_start(), z tą różnicą,
- * że działa na wątkach, nie procesach. Jest dostępna wyłącznie gdy podczas
- * kompilacji włączono odpowiednią opcję.
- * \param fd Wskaźnik na zmienną, gdzie zostanie umieszczony deskryptor gniazda
- * \param priv_data Wskaźnik na zmienną, gdzie zostanie umieszczony wskaźnik
- * do prywatnych danych wątku rozwiązującego nazwę
- * \param hostname Nazwa serwera do rozwiązania
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-static int gg_resolver_pthread_start(int *fd, void **priv_data, const char *hostname)
- struct gg_resolver_pthread_data *data = NULL;
- int pipes[2], new_errno;
- gg_debug(GG_DEBUG_FUNCTION, "** gg_resolver_pthread_start(%p, %p, \"%s\");\n", fd, priv_data, hostname);
- if (fd == NULL || priv_data == NULL || hostname == NULL) {
- gg_debug(GG_DEBUG_MISC, "// gg_resolver_pthread_start() invalid arguments\n");
- data = malloc(sizeof(struct gg_resolver_pthread_data));
- gg_debug(GG_DEBUG_MISC, "// gg_resolver_pthread_start() out of memory for resolver data\n");
- if (socketpair(AF_LOCAL, SOCK_STREAM, 0, pipes) == -1) {
- gg_debug(GG_DEBUG_MISC, "// gg_resolver_pthread_start() unable "
- "to create pipes (errno=%d, %s)\n",
- errno, strerror(errno));
- data->hostname = strdup(hostname);
- if (data->hostname == NULL) {
- gg_debug(GG_DEBUG_MISC, "// gg_resolver_pthread_start() out of memory\n");
- if (pthread_create(&data->thread, NULL, gg_resolver_pthread_thread, data)) {
- gg_debug(GG_DEBUG_MISC, "// gg_resolver_pthread_start() unable to create thread\n");
- gg_debug(GG_DEBUG_MISC, "// gg_resolver_pthread_start() %p\n", data);
-#endif /* GG_CONFIG_HAVE_PTHREAD */
- * \internal Struktura przekazywana do wątku rozwiązującego nazwę.
-struct gg_resolver_win32_data {
- HANDLE thread; /*< Uchwyt wątku */
- CRITICAL_SECTION mutex; /*< Semafor wątku */
- char *hostname; /*< Nazwa serwera */
- int wfd; /*< Deskryptor do zapisu */
- int orphan; /*< Wątek powinien sam po sobie posprzątać */
- int finished; /*< Wątek już skończył pracę */
- * \internal Wątek rozwiązujący nazwę.
- * \param arg Wskaźnik na strukturę \c gg_resolver_win32_data
-static DWORD WINAPI gg_resolver_win32_thread(void *arg)
- struct gg_resolver_win32_data *data = arg;
- result = gg_resolver_run(data->wfd, data->hostname, 0);
- EnterCriticalSection(&data->mutex);
- is_orphan = data->orphan;
- LeaveCriticalSection(&data->mutex);
- CloseHandle(data->thread);
- DeleteCriticalSection(&data->mutex);
- return 0; /* żeby kompilator nie marudził */
- * \internal Rozwiązuje nazwę serwera w osobnym wątku.
- * Funkcja działa analogicznie do \c gg_resolver_pthread_start(), z tą różnicą,
- * że działa na wątkach Win32. Jest dostępna wyłącznie przy kompilacji dla
- * \param fd Wskaźnik na zmienną, gdzie zostanie umieszczony deskryptor gniazda
- * \param priv_data Wskaźnik na zmienną, gdzie zostanie umieszczony wskaźnik
- * do prywatnych danych wątku rozwiązującego nazwę
- * \param hostname Nazwa serwera do rozwiązania
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-static int gg_resolver_win32_start(int *fd, void **priv_data, const char *hostname)
- struct gg_resolver_win32_data *data = NULL;
- int pipes[2], new_errno;
- CRITICAL_SECTION *mutex = NULL;
- gg_debug(GG_DEBUG_FUNCTION, "** gg_resolver_win32_start(%p, %p, \"%s\");\n", fd, priv_data, hostname);
- if (fd == NULL || priv_data == NULL || hostname == NULL) {
- gg_debug(GG_DEBUG_MISC, "// gg_resolver_win32_start() invalid arguments\n");
- data = malloc(sizeof(struct gg_resolver_win32_data));
- gg_debug(GG_DEBUG_MISC, "// gg_resolver_win32_start() out of memory for resolver data\n");
- if (socketpair(AF_LOCAL, SOCK_STREAM, 0, pipes) == -1) {
- gg_debug(GG_DEBUG_MISC, "// gg_resolver_win32_start() unable to "
- "create pipes (errno=%d, %s)\n",
- errno, strerror(errno));
- data->hostname = strdup(hostname);
- if (data->hostname == NULL) {
- gg_debug(GG_DEBUG_MISC, "// gg_resolver_win32_start() out of memory\n");
- InitializeCriticalSection(mutex);
- data->thread = CreateThread(NULL, 0, gg_resolver_win32_thread, data, 0, NULL);
- gg_debug(GG_DEBUG_MISC, "// gg_resolver_win32_start() unable to create thread\n");
- gg_debug(GG_DEBUG_MISC, "// gg_resolver_win32_start() %p\n", data);
- DeleteCriticalSection(mutex);
- * \internal Usuwanie zasobów po wątku rozwiązywaniu nazwy.
- * Funkcja wywoływana po zakończeniu rozwiązanywania nazwy lub przy zwalnianiu
- * zasobów sesji podczas rozwiązywania nazwy.
- * \param priv_data Wskaźnik na zmienną przechowującą wskaźnik do prywatnych
- * \param force Flaga usuwania zasobów przed zakończeniem działania
-static void gg_resolver_win32_cleanup(void **priv_data, int force)
- struct gg_resolver_win32_data *data;
- if (priv_data == NULL || *priv_data == NULL)
- data = (struct gg_resolver_win32_data *) *priv_data;
- if (WaitForSingleObject(data->thread, 0) == WAIT_TIMEOUT) {
- /* We cannot call TerminateThread here - it doesn't
- * release critical section locks (see MSDN docs).
- * if (force) TerminateThread(data->thread, 0);
- EnterCriticalSection(&data->mutex);
- finished = data->finished;
- LeaveCriticalSection(&data->mutex);
- CloseHandle(data->thread);
- DeleteCriticalSection(&data->mutex);
- * Ustawia sposób rozwiązywania nazw w sesji.
- * \param gs Struktura sesji
- * \param type Sposób rozwiązywania nazw (patrz \ref build-resolver)
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_session_set_resolver(struct gg_session *gs, gg_resolver_t type)
- GG_SESSION_CHECK(gs, -1);
- if (type == GG_RESOLVER_DEFAULT) {
- if (gg_global_resolver_type != GG_RESOLVER_DEFAULT) {
- gs->resolver_type = gg_global_resolver_type;
- gs->resolver_start = gg_global_resolver_start;
- gs->resolver_cleanup = gg_global_resolver_cleanup;
-#ifdef GG_CONFIG_HAVE_PTHREAD
- type = GG_RESOLVER_PTHREAD;
- type = GG_RESOLVER_WIN32;
-#elif defined(GG_CONFIG_HAVE_FORK)
- type = GG_RESOLVER_FORK;
-#ifdef GG_CONFIG_HAVE_FORK
- gs->resolver_type = type;
- gs->resolver_start = gg_resolver_fork_start;
- gs->resolver_cleanup = gg_resolver_fork_cleanup;
-#ifdef GG_CONFIG_HAVE_PTHREAD
- case GG_RESOLVER_PTHREAD:
- gs->resolver_type = type;
- gs->resolver_start = gg_resolver_pthread_start;
- gs->resolver_cleanup = gg_resolver_pthread_cleanup;
- case GG_RESOLVER_WIN32:
- gs->resolver_type = type;
- gs->resolver_start = gg_resolver_win32_start;
- gs->resolver_cleanup = gg_resolver_win32_cleanup;
- * Zwraca sposób rozwiązywania nazw w sesji.
- * \param gs Struktura sesji
- * \return Sposób rozwiązywania nazw
-gg_resolver_t gg_session_get_resolver(struct gg_session *gs)
- GG_SESSION_CHECK(gs, (gg_resolver_t) -1);
- return gs->resolver_type;
- * Ustawia własny sposób rozwiązywania nazw w sesji.
- * \param gs Struktura sesji
- * \param resolver_start Funkcja rozpoczynająca rozwiązywanie nazwy
- * \param resolver_cleanup Funkcja zwalniająca zasoby
- * Parametry funkcji rozpoczynającej rozwiązywanie nazwy wyglądają następująco:
- * - \c "int *fd" — wskaźnik na zmienną, gdzie zostanie umieszczony deskryptor gniazda
- * - \c "void **priv_data" — wskaźnik na zmienną, gdzie można umieścić
- * wskaźnik do prywatnych danych na potrzeby rozwiązywania nazwy
- * - \c "const char *name" — nazwa serwera do rozwiązania
- * Parametry funkcji zwalniającej zasoby wyglądają następująco:
- * - \c "void **priv_data" — wskaźnik na zmienną przechowującą wskaźnik
- * do prywatnych danych, należy go ustawić na \c NULL po zakończeniu
- * - \c "int force" — flaga mówiąca o tym, że zasoby są zwalniane przed
- * zakończeniem rozwiązywania nazwy, np. z powodu zamknięcia sesji.
- * Własny kod rozwiązywania nazwy powinien stworzyć potok, parę gniazd lub
- * inny deskryptor pozwalający na co najmniej odbiór danych i przekazać go
- * w parametrze \c fd. Na platformie Windows możliwe jest przekazanie jedynie
- * deskryptora gniazda. Po zakończeniu rozwiązywania nazwy powinien wysłać
- * otrzymany adres IP w postaci sieciowej (big-endian) do deskryptora. Jeśli
- * rozwiązywanie nazwy się nie powiedzie, należy wysłać \c INADDR_NONE.
- * Następnie zostanie wywołana funkcja zwalniająca zasoby z parametrem
- * \c force równym \c 0. Gdyby sesja została zakończona przed rozwiązaniem
- * nazwy, np. za pomocą funkcji \c gg_logoff(), funkcja zwalniająca zasoby
- * zostanie wywołana z parametrem \c force równym \c 1.
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_session_set_custom_resolver(struct gg_session *gs,
- int (*resolver_start)(int*, void**, const char*),
- void (*resolver_cleanup)(void**, int))
- GG_SESSION_CHECK(gs, -1);
- if (resolver_start == NULL || resolver_cleanup == NULL) {
- gs->resolver_type = GG_RESOLVER_CUSTOM;
- gs->resolver_start = resolver_start;
- gs->resolver_cleanup = resolver_cleanup;
- * Ustawia sposób rozwiązywania nazw połączenia HTTP.
- * \param gh Struktura połączenia
- * \param type Sposób rozwiązywania nazw (patrz \ref build-resolver)
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_http_set_resolver(struct gg_http *gh, gg_resolver_t type)
- if (type == GG_RESOLVER_DEFAULT) {
- if (gg_global_resolver_type != GG_RESOLVER_DEFAULT) {
- gh->resolver_type = gg_global_resolver_type;
- gh->resolver_start = gg_global_resolver_start;
- gh->resolver_cleanup = gg_global_resolver_cleanup;
-#ifdef GG_CONFIG_HAVE_PTHREAD
- type = GG_RESOLVER_PTHREAD;
- type = GG_RESOLVER_WIN32;
-#elif defined(GG_CONFIG_HAVE_FORK)
- type = GG_RESOLVER_FORK;
-#ifdef GG_CONFIG_HAVE_FORK
- gh->resolver_type = type;
- gh->resolver_start = gg_resolver_fork_start;
- gh->resolver_cleanup = gg_resolver_fork_cleanup;
-#ifdef GG_CONFIG_HAVE_PTHREAD
- case GG_RESOLVER_PTHREAD:
- gh->resolver_type = type;
- gh->resolver_start = gg_resolver_pthread_start;
- gh->resolver_cleanup = gg_resolver_pthread_cleanup;
- case GG_RESOLVER_WIN32:
- gh->resolver_type = type;
- gh->resolver_start = gg_resolver_win32_start;
- gh->resolver_cleanup = gg_resolver_win32_cleanup;
- * Zwraca sposób rozwiązywania nazw połączenia HTTP.
- * \param gh Struktura połączenia
- * \return Sposób rozwiązywania nazw
-gg_resolver_t gg_http_get_resolver(struct gg_http *gh)
- return GG_RESOLVER_INVALID;
- return gh->resolver_type;
- * Ustawia własny sposób rozwiązywania nazw połączenia HTTP.
- * \param gh Struktura sesji
- * \param resolver_start Funkcja rozpoczynająca rozwiązywanie nazwy
- * \param resolver_cleanup Funkcja zwalniająca zasoby
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_http_set_custom_resolver(struct gg_http *gh,
- int (*resolver_start)(int*, void**, const char*),
- void (*resolver_cleanup)(void**, int))
- if (gh == NULL || resolver_start == NULL || resolver_cleanup == NULL) {
- gh->resolver_type = GG_RESOLVER_CUSTOM;
- gh->resolver_start = resolver_start;
- gh->resolver_cleanup = resolver_cleanup;
- * Ustawia sposób rozwiązywania nazw globalnie dla biblioteki.
- * \param type Sposób rozwiązywania nazw (patrz \ref build-resolver)
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_global_set_resolver(gg_resolver_t type)
- case GG_RESOLVER_DEFAULT:
- gg_global_resolver_type = type;
- gg_global_resolver_start = NULL;
- gg_global_resolver_cleanup = NULL;
-#ifdef GG_CONFIG_HAVE_FORK
- gg_global_resolver_type = type;
- gg_global_resolver_start = gg_resolver_fork_start;
- gg_global_resolver_cleanup = gg_resolver_fork_cleanup;
-#ifdef GG_CONFIG_HAVE_PTHREAD
- case GG_RESOLVER_PTHREAD:
- gg_global_resolver_type = type;
- gg_global_resolver_start = gg_resolver_pthread_start;
- gg_global_resolver_cleanup = gg_resolver_pthread_cleanup;
- case GG_RESOLVER_WIN32:
- gg_global_resolver_type = type;
- gg_global_resolver_start = gg_resolver_win32_start;
- gg_global_resolver_cleanup = gg_resolver_win32_cleanup;
- * Zwraca sposób rozwiązywania nazw globalnie dla biblioteki.
- * \return Sposób rozwiązywania nazw
-gg_resolver_t gg_global_get_resolver(void)
- return gg_global_resolver_type;
- * Ustawia własny sposób rozwiązywania nazw globalnie dla biblioteki.
- * \param resolver_start Funkcja rozpoczynająca rozwiązywanie nazwy
- * \param resolver_cleanup Funkcja zwalniająca zasoby
- * Patrz \ref gg_session_set_custom_resolver.
- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-int gg_global_set_custom_resolver(
- int (*resolver_start)(int*, void**, const char*),
- void (*resolver_cleanup)(void**, int))
- if (resolver_start == NULL || resolver_cleanup == NULL) {
- gg_global_resolver_type = GG_RESOLVER_CUSTOM;
- gg_global_resolver_start = resolver_start;
- gg_global_resolver_cleanup = resolver_cleanup;
- * Odczytuje dane z procesu/wątku rozwiązywania nazw.
- * \param buf Wskaźnik na bufor
- * \param len Długość bufora
- * \return Patrz recv() i read().
-int gg_resolver_recv(int fd, void *buf, size_t len)
- return read(fd, buf, len);
- return recv(fd, buf, len, 0);
--- a/libpurple/protocols/gg/lib/resolver.h Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
- * (C) Copyright 2008 Wojtek Kaniewski <wojtekka@irc.pl>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-#ifndef LIBGADU_RESOLVER_H
-#define LIBGADU_RESOLVER_H
-int gg_gethostbyname_real(const char *hostname, struct in_addr **result, unsigned int *count, int pthread);
-int gg_resolver_recv(int fd, void *buf, size_t len);
-void gg_resolver_cleaner(void *data);
-#endif /* LIBGADU_RESOLVER_H */
--- a/libpurple/protocols/gg/lib/session.h Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
- * (C) Copyright 2008-2010 Wojtek Kaniewski <wojtekka@irc.pl>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-#ifndef LIBGADU_SESSION_H
-#define LIBGADU_SESSION_H
-#ifdef GG_CONFIG_HAVE_GNUTLS
-# include <gnutls/gnutls.h>
-#define GG_SESSION_CHECK(gs, result) \
-#define GG_SESSION_CHECK_CONNECTED(gs, result) \
- GG_SESSION_CHECK(gs, result); \
- if (!GG_SESSION_IS_CONNECTED(gs)) { \
-#define GG_SESSION_IS_IDLE(gs) ((gs)->state == GG_STATE_IDLE)
-#define GG_SESSION_IS_CONNECTING(gs) ((gs)->state != GG_STATE_IDLE && (gs)->state != GG_STATE_CONNECTED)
-#define GG_SESSION_IS_CONNECTED(gs) ((gs)->state == GG_STATE_CONNECTED)
-#ifdef GG_CONFIG_HAVE_GNUTLS
- gnutls_session_t session;
- gnutls_certificate_credentials_t xcred;
-#define GG_SESSION_GNUTLS(gs) ((gg_session_gnutls_t*) (gs)->ssl)->session
-#endif /* GG_CONFIG_HAVE_GNUTLS */
-#ifdef GG_CONFIG_HAVE_OPENSSL
-#define GG_SESSION_OPENSSL(gs) ((SSL*) (gs)->ssl)
-#endif /* GG_CONFIG_HAVE_OPENSSL */
-int gg_session_handle_packet(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge);
-#endif /* LIBGADU_SESSION_H */
--- a/libpurple/protocols/gg/lib/sha1.c Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,382 +0,0 @@
- * (C) Copyright 2007 Wojtek Kaniewski <wojtekka@irc.pl>
- * Public domain SHA-1 implementation by Steve Reid <steve@edmweb.com>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
- * \brief Funkcje wyznaczania skrótu SHA1
-#ifdef GG_CONFIG_HAVE_OPENSSL
-#include <openssl/sha.h>
-#elif defined(GG_CONFIG_HAVE_GNUTLS)
-#include <gnutls/gnutls.h>
-#include <gnutls/crypto.h>
-#define SHA_CTX gnutls_hash_hd_t
-#define SHA1_Init(ctx) (gnutls_hash_init((ctx), GNUTLS_DIG_SHA1) == 0 ? 1 : 0)
-#define SHA1_Update(ctx, ptr, len) (gnutls_hash(*(ctx), (ptr), (len)) == 0 ? 1 : 0)
-#define SHA1_Final(digest, ctx) (gnutls_hash_deinit(*(ctx), (digest)), 1)
-By Steve Reid <steve@edmweb.com>
-Modified by Wojtek Kaniewski <wojtekka@toxygen.net> for compatibility
-with libgadu and OpenSSL API.
-Test Vectors (from FIPS PUB 180-1)
- A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
-"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
- 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
-A million repetitions of "a"
- 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
-/* #define LITTLE_ENDIAN * This should be #define'd if true. */
-/* #define SHA1HANDSOFF * Copies data before messing with it. */
- unsigned char buffer[64];
-static void SHA1_Transform(uint32_t state[5], const unsigned char buffer[64]);
-static int SHA1_Init(SHA_CTX* context);
-static int SHA1_Update(SHA_CTX* context, const unsigned char* data, unsigned int len);
-static int SHA1_Final(unsigned char digest[20], SHA_CTX* context);
-#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
-/* blk0() and blk() perform the initial expand. */
-/* I got the idea of expanding during the round function from SSLeay */
-#ifndef GG_CONFIG_BIGENDIAN
-#define blk0(i) (block.l[i] = (rol(block.l[i], 24) & 0xFF00FF00) \
- |(rol(block.l[i], 8) & 0x00FF00FF))
-#define blk0(i) block.l[i]
-#define blk(i) (block.l[i&15] = rol(block.l[(i+13)&15]^block.l[(i+8)&15] \
- ^block.l[(i+2)&15]^block.l[i&15], 1))
-/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
-/* style:comma:start-ignore */
-#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
-#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
-#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
-#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
-#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
-/* style:comma:end-ignore */
-/* Hash a single 512-bit block. This is the core of the algorithm. */
-static void SHA1_Transform(uint32_t state[5], const unsigned char buffer[64])
- memcpy(&block, buffer, sizeof(block));
- /* Copy context->state[] to working vars */
- /* 4 rounds of 20 operations each. Loop unrolled. */
- /* style:comma:start-ignore */
- R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
- R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
- R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
- R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
- R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
- R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
- R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
- R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
- R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
- R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
- R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
- R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
- R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
- R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
- R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
- R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
- R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
- R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
- R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
- R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
- /* style:comma:end-ignore */
- /* Add the working vars back into context.state[] */
- memset(&a, 0, sizeof(a));
- memset(&b, 0, sizeof(b));
- memset(&c, 0, sizeof(c));
- memset(&d, 0, sizeof(d));
- memset(&e, 0, sizeof(e));
-/* SHA1_Init - Initialize new context */
-static int SHA1_Init(SHA_CTX* context)
- /* SHA1 initialization constants */
- context->state[0] = 0x67452301;
- context->state[1] = 0xEFCDAB89;
- context->state[2] = 0x98BADCFE;
- context->state[3] = 0x10325476;
- context->state[4] = 0xC3D2E1F0;
- context->count[0] = context->count[1] = 0;
-/* Run your data through this. */
-static int SHA1_Update(SHA_CTX* context, const unsigned char* data, unsigned int len)
- j = (context->count[0] >> 3) & 63;
- if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
- context->count[1] += (len >> 29);
- memcpy(&context->buffer[j], data, (i = 64-j));
- SHA1_Transform(context->state, context->buffer);
- for ( ; i + 63 < len; i += 64) {
- SHA1_Transform(context->state, &data[i]);
- memcpy(&context->buffer[j], &data[i], len - i);
-/* Add padding and return the message digest. */
-static int SHA1_Final(unsigned char digest[20], SHA_CTX* context)
-unsigned char finalcount[8];
- for (i = 0; i < 8; i++) {
- finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
- >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
- SHA1_Update(context, (const unsigned char *)"\200", 1);
- while ((context->count[0] & 504) != 448) {
- SHA1_Update(context, (const unsigned char *)"\0", 1);
- SHA1_Update(context, finalcount, 8); /* Should cause a SHA1_Transform() */
- for (i = 0; i < 20; i++) {
- digest[i] = (unsigned char)
- ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
- memset(context->buffer, 0, 64);
- memset(context->state, 0, 20);
- memset(context->count, 0, 8);
- memset(&finalcount, 0, 8);
-#ifdef SHA1HANDSOFF /* make SHA1_Transform overwrite it's own static vars */
- SHA1_Transform(context->state, context->buffer);
-#endif /* GG_CONFIG_HAVE_OPENSSL */
- * \internal Liczy skrót SHA1 z ziarna i hasła.
- * \param password Hasło
- * \param result Bufor na wynik funkcji skrótu (20 bajtów)
-int gg_login_hash_sha1_2(const char *password, uint32_t seed, uint8_t *result)
- if (!SHA1_Update(&ctx, (const unsigned char*) password, strlen(password)))
- if (!SHA1_Update(&ctx, (uint8_t*) &seed, 4))
- if (!SHA1_Final(result, &ctx))
- /* Zwolnij zasoby. Tylko GnuTLS przyjęłoby NULL zamiast result, więc przekaż result. */
- (void)SHA1_Final(result, &ctx);
- * \internal Liczy skrót SHA1 z fragmentu pliku.
- * \param fd Deskryptor pliku
- * \param ctx Kontekst SHA-1
- * \param pos Położenie fragmentu pliku
- * \param len Długość fragmentu pliku
-static int gg_file_hash_sha1_part(int fd, SHA_CTX *ctx, off_t pos, size_t len)
- unsigned char buf[4096];
- if (lseek(fd, pos, SEEK_SET) == (off_t) -1) {
- if (chunk_len > sizeof(buf))
- chunk_len = sizeof(buf);
- res = read(fd, buf, chunk_len);
- if (res == -1 && errno != EINTR)
- if (!SHA1_Update(ctx, buf, res)) {
- * \internal Liczy skrót SHA1 z pliku.
- * Dla plików poniżej 10MB liczony jest skrót z całego pliku, dla plików
- * powyżej 10MB liczy się 9 jednomegabajtowych fragmentów.
- * \param fd Deskryptor pliku
- * \param result Bufor na wynik funkcji skrótu (20 bajtów)
-int gg_file_hash_sha1(int fd, uint8_t *result)
- const size_t part_len = 1048576;
- if ((pos = lseek(fd, 0, SEEK_CUR)) == (off_t) -1)
- if ((len = lseek(fd, 0, SEEK_END)) == (off_t) -1)
- if (lseek(fd, 0, SEEK_SET) == (off_t) -1)
- if (len <= (off_t)part_len * 10) {
- res = gg_file_hash_sha1_part(fd, &ctx, 0, len);
- for (i = 0; i < 9; i++) {
- off_t part_pos = (len - part_len) / 9 * i;
- res = gg_file_hash_sha1_part(fd, &ctx, part_pos, part_len);
- if (!SHA1_Final(result, &ctx))
- if (lseek(fd, pos, SEEK_SET) == (off_t) -1)
--- a/libpurple/protocols/gg/lib/strman.h Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
- * (C) Copyright 2011 Bartosz Brachaczek <b.brachaczek@gmail.com>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
- * \brief Makra zapewniające kompatybilność API do obsługi operacji na stringach na różnych systemach
-#ifndef LIBGADU_STRMAN_H
-#define LIBGADU_STRMAN_H
-# define snprintf(str, size, format, ...) _snprintf_s(str, size, _TRUNCATE, format, __VA_ARGS__)
-# define vsnprintf(str, size, format, ap) vsnprintf_s(str, size, _TRUNCATE, format, ap)
-# define strcasecmp _stricmp
-# define strncasecmp _strnicmp
-#endif /* LIBGADU_STRMAN_H */
--- a/libpurple/protocols/gg/lib/tvbuff.c Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,607 +0,0 @@
- * (C) Copyright 2012 Tomek Wasilczyk <www.wasilczyk.pl>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
- * \brief Bufor wspierający obsługę pakietów typu Type-Value(s)
- * \internal Tworzy nową instancję bufora.
- * \param buffer Bufor źródłowy; nie może być modyfikowany (w szczególności
- * zwalniany) przez cały okres korzystania z jego opakowanej wersji.
- * \param length Długość bufora źródłowego.
- * \return Zaalokowane opakowanie bufora - musi być zwolnione przez free lub
-gg_tvbuff_t *gg_tvbuff_new(const char *buffer, size_t length)
- tvb = malloc(sizeof(gg_tvbuff_t));
- memset(tvb, 0, sizeof(gg_tvbuff_t));
- if (buffer == NULL && length > 0) {
- gg_debug(GG_DEBUG_ERROR, "// gg_tvbuff_new() "
- "invalid arguments\n");
- * \internal Zwalnia opakowanie bufora. Przed zwolnieniem sprawdza, czy
- * przeczytano go do końca.
- * \return Wartość różna od 0, jeżeli bufor tuż przed zwolnieniem był oznaczony
-int gg_tvbuff_close(gg_tvbuff_t *tvb)
- gg_tvbuff_expected_eob(tvb);
- valid = gg_tvbuff_is_valid(tvb);
- * \internal Sprawdza, czy wszystkie odczyty z bufora były prawidłowe.
- * \return Wartość różna od 0, jeżeli wszystkie odczyty były prawidłowe.
-int gg_tvbuff_is_valid(const gg_tvbuff_t *tvb)
- * \internal Zwraca pozostałą do odczytania liczbę bajtów w buforze.
- * \return Pozostała liczba bajtów do odczytania.
-size_t gg_tvbuff_get_remaining(const gg_tvbuff_t *tvb)
- if (!gg_tvbuff_is_valid(tvb))
- return tvb->length - tvb->offset;
- * \internal Sprawdza, czy w buforze pozostała określona liczba bajtów do
- * odczytania. Jeżeli nie została - oznacza bufor jako nieprawidłowy.
- * \param length Ilość bajtów do odczytania.
- * \return Wartość różna od 0, jeżeli można odczytać podaną liczbę bajtów.
-int gg_tvbuff_have_remaining(gg_tvbuff_t *tvb, size_t length)
- if (!gg_tvbuff_is_valid(tvb))
- if (gg_tvbuff_get_remaining(tvb) >= length)
- gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_have_remaining() failed "
- "(%" GG_SIZE_FMT " < %" GG_SIZE_FMT ")\n",
- gg_tvbuff_get_remaining(tvb), length);
- * \internal Pomija określoną liczbę bajtów w buforze. Jeżeli w wyniku ich
- * pominięcia wyjdzie poza zakres, oznacza bufor jako nieprawidłowy.
- * \param amount Liczba bajtów do pominięcia
-void gg_tvbuff_skip(gg_tvbuff_t *tvb, size_t amount)
- if (!gg_tvbuff_is_valid(tvb))
- if (tvb->offset + amount > tvb->length) {
- gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_skip() failed\n");
- * \internal Cofa się o określoną liczbę bajtów w buforze. Jeżeli cofnie przed
- * pierwszy znak, oznacza bufor jako nieprawidłowy.
- * \param amount Liczba bajtów do cofnięcia
-void gg_tvbuff_rewind(gg_tvbuff_t *tvb, size_t amount)
- if (!gg_tvbuff_is_valid(tvb))
- if (tvb->offset < amount) {
- gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_rewind() failed\n");
- * \internal Sprawdza, czy pod aktualną pozycją w buforze występuje podana
- * wartość. Jeżeli tak, przesuwa aktualną pozycję do przodu.
- * \param value Wartość do sprawdzenia
- * \return Wartość różna od 0, jeżeli znaleziono podaną wartość.
-int gg_tvbuff_match(gg_tvbuff_t *tvb, uint8_t value)
- if (!gg_tvbuff_is_valid(tvb))
- if (!gg_tvbuff_have_remaining(tvb, 1)) {
- gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_match() failed\n");
- if (tvb->buffer[tvb->offset] != value)
- * \internal Odczytuje z bufora liczbę 8-bitową.
- * \return Odczytana liczba
-uint8_t gg_tvbuff_read_uint8(gg_tvbuff_t *tvb)
- if (!gg_tvbuff_is_valid(tvb))
- if (!gg_tvbuff_have_remaining(tvb, 1)) {
- gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_read_uint8() "
- "failed at %" GG_SIZE_FMT "\n", tvb->offset);
- return tvb->buffer[tvb->offset++];
- * \internal Odczytuje z bufora liczbę 32-bitową.
- * \return Odczytana liczba
-uint32_t gg_tvbuff_read_uint32(gg_tvbuff_t *tvb)
- if (!gg_tvbuff_is_valid(tvb))
- if (!gg_tvbuff_have_remaining(tvb, 4)) {
- gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_read_uint32() "
- "failed at %" GG_SIZE_FMT "\n", tvb->offset);
- memcpy(&val, tvb->buffer + tvb->offset, 4);
- * \internal Odczytuje z bufora liczbę 64-bitową.
- * \return Odczytana liczba
-uint64_t gg_tvbuff_read_uint64(gg_tvbuff_t *tvb)
- if (!gg_tvbuff_is_valid(tvb))
- if (!gg_tvbuff_have_remaining(tvb, 8)) {
- gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_read_uint64() "
- "failed at %" GG_SIZE_FMT "\n", tvb->offset);
- memcpy(&val, tvb->buffer + tvb->offset, 8);
- * \internal Odczytuje z bufora skompresowaną liczbę całkowitą.
- * Liczba taka może być zapisana w buforze na 1-9 bajtach, w zależności
- * Skompresowana liczba jest zapisywana od najmłodszego bajtu do najstarszego
- * niezerowego. W każdym bajcie zapisuje się bit sterujący (równy 0, jeżeli jest
- * to ostatni bajt do przeczytania, lub 1 w p.p.) oraz 7 kolejnych bitów z
- * kompresowanej liczby.
- * Przykładowo, liczby mniejsze od 128 (1000.0000b) są zapisywane dokładnie tak,
- * jak uint8_t; a np. 12345 (0011.0000.0011.1001b) zostanie zapisana jako 0x60B9
- * (0110.0000.1011.1001b).
- * \return Odczytana liczba.
-uint64_t gg_tvbuff_read_packed_uint(gg_tvbuff_t *tvb)
- if (!gg_tvbuff_is_valid(tvb))
- while (gg_tvbuff_have_remaining(tvb, 1)) {
- if (!(gg_tvbuff_read_uint8(tvb) & 0x80))
- if (!gg_tvbuff_is_valid(tvb)) {
- gg_debug(GG_DEBUG_WARNING,
- "// gg_tvbuff_read_packed_uint() failed\n");
- gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_read_packed_uint() "
- "packed uint size too big: %d\n", val_len);
- for (i = 1; i <= val_len; i++) {
- uint64_t old_val = val;
- if (old_val != (val >> 7)) {
- gg_debug(GG_DEBUG_WARNING,
- "// gg_tvbuff_read_packed_uint() overflow\n");
- val |= (uint8_t)(tvb->buffer[tvb->offset - i] & ~0x80);
- * \internal Odczytuje z bufora podciąg bez kopiowania danych.
- * \param tvb Bufor źródłowy
- * \param length Ilość bajtów do odczytania
- * \return Wskaźnik na początek odczytanych danych, lub NULL w przypadku
-const char *gg_tvbuff_read_buff(gg_tvbuff_t *tvb, size_t length)
- if (!gg_tvbuff_is_valid(tvb))
- if (!gg_tvbuff_have_remaining(tvb, length)) {
- gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_get_buff() "
- "failed at %" GG_SIZE_FMT ":%" GG_SIZE_FMT "\n",
- buff = tvb->buffer + tvb->offset;
- * \internal Odczytuje z bufora podciąg kopiując go do nowego obszaru pamięci.
- * \param tvb Bufor źródłowy
- * \param buffer Bufor docelowy
- * \param length Ilość bajtów do odczytania
-void gg_tvbuff_read_buff_cpy(gg_tvbuff_t *tvb, char *buffer, size_t length)
- if (!gg_tvbuff_is_valid(tvb))
- if (!gg_tvbuff_have_remaining(tvb, length)) {
- gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_read_buff() "
- "failed at %" GG_SIZE_FMT ":%" GG_SIZE_FMT "\n",
- if (buffer == NULL && length > 0) {
- gg_debug(GG_DEBUG_ERROR, "// gg_tvbuff_new() "
- "invalid arguments\n");
- memcpy(buffer, tvb->buffer + tvb->offset, length);
- * \internal Odczytuje z bufora ciąg tekstowy (mogący zawierać dowolne znaki,
- * również \0) bez kopiowania danych.
- * \param tvb Bufor źródłowy
- * \param length Zmienna, do której zostanie zapisana długość odczytanego ciągu
- * \return Wskaźnik na początek odczytanych danych, lub NULL w przypadku
-const char *gg_tvbuff_read_str(gg_tvbuff_t *tvb, size_t *length)
- if (!gg_tvbuff_is_valid(tvb))
- str_len = gg_tvbuff_read_packed_uint(tvb);
- if (!gg_tvbuff_is_valid(tvb) ||
- !gg_tvbuff_have_remaining(tvb, str_len))
- gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_read_str() failed at "
- "%" GG_SIZE_FMT ":%d\n", offset, str_len);
- str = gg_tvbuff_read_buff(tvb, str_len);
- if (!gg_tvbuff_is_valid(tvb))
- * \internal Odczytuje z bufora ciąg tekstowy (mogący zawierać dowolne znaki,
- * również \0) kopiując go do nowego obszaru pamięci. Zwrócony ciąg będzie
- * zawsze zakończony znakiem \0.
- * \param tvb Bufor źródłowy
- * \param dst Zmienna, do której zostanie zapisany wskaźnik na odczytany ciąg.
- * Po użyciu, blok ten powinien zostać zwolniony za pomocą \c free()
- * \return Wskaźnik na początek odczytanych danych, lub NULL w przypadku
-void gg_tvbuff_read_str_dup(gg_tvbuff_t *tvb, char **dst)
- if (!gg_tvbuff_is_valid(tvb))
- str_len = gg_tvbuff_read_packed_uint(tvb);
- if (!gg_tvbuff_is_valid(tvb) ||
- !gg_tvbuff_have_remaining(tvb, str_len))
- gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_read_str_dup() failed "
- "at %" GG_SIZE_FMT ":%d\n", offset, str_len);
- str = malloc(str_len + 1);
- gg_debug(GG_DEBUG_ERROR, "// gg_tvbuff_read_str_dup() "
- "not enough free memory: %d + 1\n", str_len);
- gg_tvbuff_read_buff_cpy(tvb, str, str_len);
- gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_read_str_dup() "
- "destination already filled, freeing it...\n");
- * \internal Odczytuje z bufora identyfikator użytkownika.
- * \return Identyfikator użytkownika, lub 0 w przypadku niepowodzenia
-uin_t gg_tvbuff_read_uin(gg_tvbuff_t *tvb)
- uint32_t uin_len, full_len;
- if (!gg_tvbuff_is_valid(tvb))
- full_len = gg_tvbuff_read_packed_uint(tvb);
- uin_type = gg_tvbuff_read_uint8(tvb);
- uin_len = gg_tvbuff_read_uint8(tvb);
- if (!gg_tvbuff_is_valid(tvb))
- if (full_len != uin_len + 2 ||
- gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_read_uin() failed (1)\n");
- raw = gg_tvbuff_read_buff(tvb, uin_len);
- uin = gg_str_to_uin(raw, uin_len);
- gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_read_uin() failed (2)\n");
- * \internal Odczytuje z bufora liczbę 8-bitową i porównuje z podaną. Jeżeli te
- * się różnią, zostaje wygenerowane ostrzeżenie.
- * \param value Oczekiwana wartość
-void gg_tvbuff_expected_uint8(gg_tvbuff_t *tvb, uint8_t value)
- got = gg_tvbuff_read_uint8(tvb);
- if (!gg_tvbuff_is_valid(tvb))
- gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_expected_uint8() "
- "expected %#02x, but %#02x found at %" GG_SIZE_FMT "\n",
- * \internal Odczytuje z bufora liczbę 32-bitową i porównuje z podaną. Jeżeli te
- * się różnią, zostaje wygenerowane ostrzeżenie.
- * \param value Oczekiwana wartość
-void gg_tvbuff_expected_uint32(gg_tvbuff_t *tvb, uint32_t value)
- got = gg_tvbuff_read_uint32(tvb);
- if (!gg_tvbuff_is_valid(tvb))
- gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_expected_uint32() "
- "expected %#08x, but %#08x found at %" GG_SIZE_FMT "\n",
- * \internal Oczekuje końca bufora. Jeżeli w buforze są jeszcze dane do
- * przeczytania, generuje ostrzeżenie.
-void gg_tvbuff_expected_eob(const gg_tvbuff_t *tvb)
- if (!gg_tvbuff_is_valid(tvb))
- if (gg_tvbuff_get_remaining(tvb) != 0)
- gg_debug(GG_DEBUG_WARNING, "// gg_tvbuff_expected_eob() "
- "unexpected %" GG_SIZE_FMT " bytes, first=%#02x\n",
- gg_tvbuff_get_remaining(tvb),
- tvb->buffer[tvb->offset]);
--- a/libpurple/protocols/gg/lib/tvbuff.h Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
- * (C) Copyright 2012 Tomek Wasilczyk <www.wasilczyk.pl>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-#ifndef LIBGADU_TVBUFF_H
-#define LIBGADU_TVBUFF_H
-typedef struct gg_tvbuff gg_tvbuff_t;
-gg_tvbuff_t * gg_tvbuff_new(const char *buffer, size_t length);
-int gg_tvbuff_close(gg_tvbuff_t *tvb);
-int gg_tvbuff_is_valid(const gg_tvbuff_t *tvb);
-size_t gg_tvbuff_get_remaining(const gg_tvbuff_t *tvb);
-int gg_tvbuff_have_remaining(gg_tvbuff_t *tvb, size_t length);
-void gg_tvbuff_skip(gg_tvbuff_t *tvb, size_t amount);
-void gg_tvbuff_rewind(gg_tvbuff_t *tvb, size_t amount);
-int gg_tvbuff_match(gg_tvbuff_t *tvb, uint8_t value);
-uint8_t gg_tvbuff_read_uint8(gg_tvbuff_t *tvb);
-uint32_t gg_tvbuff_read_uint32(gg_tvbuff_t *tvb);
-uint64_t gg_tvbuff_read_uint64(gg_tvbuff_t *tvb);
-uint64_t gg_tvbuff_read_packed_uint(gg_tvbuff_t *tvb);
-const char * gg_tvbuff_read_buff(gg_tvbuff_t *tvb, size_t length);
-void gg_tvbuff_read_buff_cpy(gg_tvbuff_t *tvb, char *buffer, size_t length);
-const char * gg_tvbuff_read_str(gg_tvbuff_t *tvb, size_t *length);
-void gg_tvbuff_read_str_dup(gg_tvbuff_t *tvb, char **dst);
-uin_t gg_tvbuff_read_uin(gg_tvbuff_t *tvb);
-void gg_tvbuff_expected_uint8(gg_tvbuff_t *tvb, uint8_t value);
-void gg_tvbuff_expected_uint32(gg_tvbuff_t *tvb, uint32_t value);
-void gg_tvbuff_expected_eob(const gg_tvbuff_t *tvb);
-#endif /* LIBGADU_TVBUFF_H */
--- a/libpurple/protocols/gg/lib/tvbuilder.c Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,426 +0,0 @@
- * (C) Copyright 2012 Tomek Wasilczyk <www.wasilczyk.pl>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
- * \brief Bufor wspierający budowanie pakietów typu Type-Value(s)
-static char *gg_tvbuilder_extend(gg_tvbuilder_t *tvb, size_t length);
- * \internal Tworzy nową instancję bufora.
- * \param gs Struktura sesji
- * \param ge Struktura zdarzenia
- * \return Zaalokowany bufor - musi być zwolniony przez gg_tvbuilder_free,
- * gg_tvbuilder_fail lub gg_tvbuilder_send.
-gg_tvbuilder_t *gg_tvbuilder_new(struct gg_session *gs, struct gg_event *ge)
- tvb = malloc(sizeof(gg_tvbuilder_t));
- memset(tvb, 0, sizeof(gg_tvbuilder_t));
- gg_debug(GG_DEBUG_ERROR, "// gg_tvbuilder_new() "
- "invalid arguments\n");
- * \internal Zwalnia bufor.
-void gg_tvbuilder_free(gg_tvbuilder_t *tvb)
- * \internal Zwalnia bufor i generuje błąd połączenia.
- * \param failure Powód błędu
-void gg_tvbuilder_fail(gg_tvbuilder_t *tvb, enum gg_failure_t failure)
- gg_debug(GG_DEBUG_WARNING, "// gg_tvbuilder_fail() "
- tvb->ge->type = GG_EVENT_CONN_FAILED;
- tvb->ge->event.failure = failure;
- tvb->gs->state = GG_STATE_IDLE;
- gg_tvbuilder_free(tvb);
- * \internal Próbuje wysłać zawartość bufora i go zwalnia.
- * \param type Typ pakietu
- * \return 1 jeśli się powiodło, 0 w p.p.
-int gg_tvbuilder_send(gg_tvbuilder_t *tvb, int type)
- enum gg_failure_t failure;
- gg_debug(GG_DEBUG_WARNING, "// gg_tvbuilder_send() "
- if (!gg_tvbuilder_is_valid(tvb)) {
- gg_debug_session(tvb->gs, GG_DEBUG_ERROR, "// gg_tvbuilder_send() "
- failure = GG_FAILURE_INTERNAL;
- const char *buffer = (tvb->length > 0) ? tvb->buffer : "";
- ret = gg_send_packet(tvb->gs, type, buffer, tvb->length, NULL);
- failure = GG_FAILURE_WRITING;
- gg_debug_session(tvb->gs, GG_DEBUG_ERROR,
- "// gg_tvbuilder_send() "
- "sending packet %#x failed. (errno=%d, %s)\n",
- type, errno, strerror(errno));
- gg_tvbuilder_fail(tvb, failure);
- gg_tvbuilder_free(tvb);
- * \internal Sprawdza, czy wszystkie zapisy do bufora były prawidłowe.
- * \return Wartość różna od 0, jeżeli wszystkie zapisy były prawidłowe.
-int gg_tvbuilder_is_valid(const gg_tvbuilder_t *tvb)
- * \internal Sprawdza rozmiar bufora.
- * \return Rozmiar bufora
-size_t gg_tvbuilder_get_size(const gg_tvbuilder_t *tvb)
- if (!gg_tvbuilder_is_valid(tvb))
- * \internal Określa oczekiwaną liczbę bajtów, o którą zostanie rozszerzony
- * Funkcja powoduje jedynie wzrost wydajności poprzez zmniejszenie ilości
- * \param length Oczekiwana liczba bajtów.
-void gg_tvbuilder_expected_size(gg_tvbuilder_t *tvb, size_t length)
- if (!gg_tvbuilder_is_valid(tvb) || length == 0)
- length_new = tvb->length + length;
- if (length_new <= tvb->alloc_length)
- if (tvb->alloc_length > 0) {
- gg_debug(GG_DEBUG_MISC, "// gg_tvbuilder_expected_size(%p, %"
- GG_SIZE_FMT ") realloc from %" GG_SIZE_FMT " to %"
- tvb, length, tvb->alloc_length, length_new);
- buff_new = realloc(tvb->buffer, length_new);
- if (buff_new != NULL) {
- tvb->buffer = buff_new;
- tvb->alloc_length = length_new;
- gg_debug(GG_DEBUG_ERROR, "// gg_tvbuilder_expected_size(%p, %"
- GG_SIZE_FMT ") out of memory (new length: %" GG_SIZE_FMT
- ")\n", tvb, length, length_new);
- * \internal Poszerza bufor o podaną liczbę bajtów.
- * \param length Liczba bajtów do dodania
- * \return Początek nowo dodanego bloku bufora
-static char * gg_tvbuilder_extend(gg_tvbuilder_t *tvb, size_t length)
- gg_tvbuilder_expected_size(tvb, length);
- if (!gg_tvbuilder_is_valid(tvb))
- length_old = tvb->length;
- return tvb->buffer + length_old;
- * \internal Skraca bufor o podaną liczbę bajtów
- * \param length Ilość bajtów do skrócenia
-void gg_tvbuilder_strip(gg_tvbuilder_t *tvb, size_t length)
- if (!gg_tvbuilder_is_valid(tvb))
- if (length > tvb->length) {
- gg_debug(GG_DEBUG_WARNING, "// gg_tvbuilder_strip() "
- * \internal Zapisuje do bufora liczbę 8-bitową.
- * \param value Wartość do zapisania
-void gg_tvbuilder_write_uint8(gg_tvbuilder_t *tvb, uint8_t value)
- gg_tvbuilder_write_buff(tvb, (const char *)&value, 1);
- * \internal Zapisuje do bufora liczbę 32-bitową.
- * \param value Wartość do zapisania
-void gg_tvbuilder_write_uint32(gg_tvbuilder_t *tvb, uint32_t value)
- value = gg_fix32(value);
- gg_tvbuilder_write_buff(tvb, (const char *)&value, 4);
- * \internal Zapisuje do bufora liczbę 64-bitową.
- * \param value Wartość do zapisania
-void gg_tvbuilder_write_uint64(gg_tvbuilder_t *tvb, uint64_t value)
- value = gg_fix64(value);
- gg_tvbuilder_write_buff(tvb, (const char *)&value, 8);
- * \internal Zapisuje do bufora liczbę 1-9 bajtową.
- * \param value Wartość do zapisania
- * \see gg_tvbuff_read_packed_uint
-void gg_tvbuilder_write_packed_uint(gg_tvbuilder_t *tvb, uint64_t value)
- if (!gg_tvbuilder_is_valid(tvb))
- gg_debug(GG_DEBUG_WARNING, "// gg_tvbuilder_write_packed_uint() "
- "int size too big (%d): %" PRIu64 "\n", val_len, value);
- for (i = 0; i < val_len; i++) {
- uint8_t raw = val_curr & 0x7F;
- gg_tvbuilder_write_buff(tvb, (const char*)buff, val_len);
- * \internal Zapisuje do bufora zawartość innego bufora.
- * \param tvb Bufor docelowy
- * \param buffer Bufor źródłowy
- * \param length Ilość danych do skopiowania
-void gg_tvbuilder_write_buff(gg_tvbuilder_t *tvb, const char *buffer,
- char *buff = gg_tvbuilder_extend(tvb, length);
- memcpy(buff, buffer, length);
- * \internal Zapisuje do bufora ciąg tekstowy (mogący zawierać znaki \0).
- * \param tvb Bufor docelowy
- * \param buffer Bufor źródłowy
- * \param length Długość tekstu, lub -1, jeżeli ma zostać wyliczona
- * automatycznie (do pierwszego znaku \0)
-void gg_tvbuilder_write_str(gg_tvbuilder_t *tvb, const char *buffer,
- if (!gg_tvbuilder_is_valid(tvb))
- length = strlen(buffer);
- gg_tvbuilder_write_packed_uint(tvb, length);
- gg_tvbuilder_write_buff(tvb, buffer, length);
- * \internal Zapisuje do bufora identyfikator użytkownika.
- * \param uin Identyfikator użytkownika
-void gg_tvbuilder_write_uin(gg_tvbuilder_t *tvb, uin_t uin)
- uin_len = snprintf(uin_str, sizeof(uin_str), "%u", uin);
- gg_tvbuilder_write_uint8(tvb, 0x00);
- gg_tvbuilder_write_str(tvb, uin_str, uin_len);
--- a/libpurple/protocols/gg/lib/tvbuilder.h Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
- * (C) Copyright 2012 Tomek Wasilczyk <www.wasilczyk.pl>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License Version
- * 2.1 as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-#ifndef LIBGADU_TVBUILDER_H
-#define LIBGADU_TVBUILDER_H
-typedef struct gg_tvbuilder gg_tvbuilder_t;
-gg_tvbuilder_t * gg_tvbuilder_new(struct gg_session *gs, struct gg_event *ge);
-void gg_tvbuilder_free(gg_tvbuilder_t *tvb);
-void gg_tvbuilder_fail(gg_tvbuilder_t *tvb, enum gg_failure_t failure);
-int gg_tvbuilder_send(gg_tvbuilder_t *tvb, int type);
-int gg_tvbuilder_is_valid(const gg_tvbuilder_t *tvb);
-size_t gg_tvbuilder_get_size(const gg_tvbuilder_t *tvb);
-void gg_tvbuilder_expected_size(gg_tvbuilder_t *tvb, size_t length);
-void gg_tvbuilder_strip(gg_tvbuilder_t *tvb, size_t length);
-void gg_tvbuilder_write_uint8(gg_tvbuilder_t *tvb, uint8_t value);
-void gg_tvbuilder_write_uint32(gg_tvbuilder_t *tvb, uint32_t value);
-void gg_tvbuilder_write_uint64(gg_tvbuilder_t *tvb, uint64_t value);
-void gg_tvbuilder_write_packed_uint(gg_tvbuilder_t *tvb, uint64_t value);
-void gg_tvbuilder_write_buff(gg_tvbuilder_t *tvb, const char *buffer, size_t length);
-void gg_tvbuilder_write_str(gg_tvbuilder_t *tvb, const char *buffer, ssize_t length);
-void gg_tvbuilder_write_uin(gg_tvbuilder_t *tvb, uin_t uin);
-#endif /* LIBGADU_TVBUILDER_H */
--- a/libpurple/protocols/gg/tcpsocket.c Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/protocols/gg/tcpsocket.c Sun Oct 30 12:03:44 2016 +0300
@@ -30,32 +30,100 @@
-#include "purple-socket.h"
+ GSocketConnection *conn; + GCancellable *cancellable; +ggp_tcp_socket_data_free(GGPTcpSocketData *data) + g_return_if_fail(data != NULL); + if (data->cancellable != NULL) { + g_cancellable_cancel(data->cancellable); + g_clear_object(&data->cancellable); + if (data->conn != NULL) { + purple_gio_graceful_close(G_IO_STREAM(data->conn), NULL, NULL); + g_clear_object(&data->conn); -ggp_tcpsocket_connected(PurpleSocket *ps, const gchar *error, gpointer priv_gg)
+ggp_tcpsocket_connected(GObject *source, GAsyncResult *res, gpointer user_data) - PurpleConnection *gc = purple_socket_get_connection(ps);
- GGPInfo *info = purple_connection_get_protocol_data(gc);
+ GGPTcpSocketData *data = user_data; + GSocketConnection *conn; + conn = g_socket_client_connect_to_host_finish(G_SOCKET_CLIENT(source), - PURPLE_ASSERT_CONNECTION_IS_VALID(gc);
+ if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + /* The connection was already closed, return now */
- fd = purple_socket_get_fd(ps);
+ purple_debug_error("gg", "socket failed to connect: %s", - if (!gg_socket_manager_connected(ps, priv_gg, fd)) {
- purple_debug_error("gg", "socket not handled");
- purple_socket_destroy(ps);
+ socket = g_socket_connection_get_socket(data->conn); + fd = g_socket_get_fd(socket);
- purple_input_remove(info->inpa);
+ /* XXX: For some reason if you try to connect and then immediately + * disconnect, this gets into a state where ggp_tcpsocket_close() + * isn't called. The cancellable is therefore not cancelled, and + * the connection is never closed. Guard against that state here. + if (data->gc == NULL || + !g_list_find(purple_connections_get_all(), data->gc)) { + purple_debug_error("gg", + "disconnected without closing connection: %p", + ggp_tcp_socket_data_free(data); + if (!gg_socket_manager_connected(data, data->priv_gg, fd)) { + purple_debug_error("gg", "socket not handled"); + ggp_tcp_socket_data_free(data); + info = purple_connection_get_protocol_data(data->gc); + g_source_remove(info->inpa); if (info->session->fd < 0)
+ /* XXX: This works, but not recommended to use GSocket FDs directly */ info->inpa = purple_input_add(info->session->fd,
ggp_tcpsocket_inputcond_gg_to_purple(info->session->check),
- ggp_async_login_handler, gc);
+ ggp_async_login_handler, data->gc); @@ -63,7 +131,9 @@
int is_async, void *priv)
PurpleConnection *gc = _gc;
+ GGPTcpSocketData *data; PURPLE_ASSERT_CONNECTION_IS_VALID(gc);
g_return_val_if_fail(!purple_connection_is_disconnecting(gc), NULL);
@@ -74,40 +144,100 @@
purple_debug_misc("gg", "ggp_tcpsocket_connect(%p, %s:%d, %s, %p)",
gc, host, port, is_tls ? "tls" : "tcp", priv);
- ps = purple_socket_new(gc);
- purple_socket_set_tls(ps, is_tls);
- purple_socket_set_host(ps, host);
- purple_socket_set_port(ps, port);
- if (!purple_socket_connect(ps, ggp_tcpsocket_connected, priv)) {
- purple_socket_destroy(ps);
+ client = purple_gio_socket_client_new( + purple_connection_get_account(gc), &error); + purple_debug_error("gg", "unable to connect: %s",
+ g_socket_client_set_tls(client, is_tls); + data = g_new0(GGPTcpSocketData, 1); + data->cancellable = g_cancellable_new(); + g_socket_client_connect_to_host_async(client, host, port, + data->cancellable, ggp_tcpsocket_connected, data); + g_object_unref(client); -ggp_tcpsocket_close(void *_gc, void *_ps)
+ggp_tcpsocket_close(void *_gc, void *_data) - PurpleSocket *ps = _ps;
+ GGPTcpSocketData *data = _data; - purple_socket_destroy(ps);
+ ggp_tcp_socket_data_free(data); -ggp_tcpsocket_read(void *_gc, void *_ps, unsigned char *buffer, size_t bufsize)
+ggp_tcpsocket_read(void *_gc, void *_data, unsigned char *buffer, size_t bufsize) - PurpleSocket *ps = _ps;
+ GGPTcpSocketData *data = _data; + GPollableInputStream *input; + if (data->conn == NULL) { + input = G_POLLABLE_INPUT_STREAM( + g_io_stream_get_input_stream(G_IO_STREAM(data->conn))); + ret = g_pollable_input_stream_read_nonblocking(input, + buffer, bufsize, NULL, &error); - return purple_socket_read(ps, buffer, bufsize);
+ if (g_error_matches(error, + G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { + purple_debug_error("gg", "socket read error: %s", -ggp_tcpsocket_write(void *_gc, void *_ps, const unsigned char *data, size_t len)
+ggp_tcpsocket_write(void *_gc, void *_data, const unsigned char *data_buf, size_t len) - PurpleSocket *ps = _ps;
+ GGPTcpSocketData *data = _data; + GPollableOutputStream *output; + if (data->conn == NULL) { + output = G_POLLABLE_OUTPUT_STREAM( + g_io_stream_get_output_stream(G_IO_STREAM(data->conn))); + ret = g_pollable_output_stream_write_nonblocking(output, + data_buf, len, NULL, &error); - return purple_socket_write(ps, data, len);
+ if (g_error_matches(error, + G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { + purple_debug_error("gg", "socket write error: %s", --- a/libpurple/protocols/irc/msgs.c Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/protocols/irc/msgs.c Sun Oct 30 12:03:44 2016 +0300
@@ -1564,6 +1564,8 @@
PurpleConnection *gc = purple_account_get_connection(irc->account);
const char *mech_list = NULL;
if (strncmp(args[2], "sasl ", 6))
@@ -1628,6 +1630,15 @@
irc->sasl_mechs = g_string_new(mech_list);
+ /* Drop EXTERNAL mechanism since we don't support it */ + if ((pos = strstr(irc->sasl_mechs->str, "EXTERNAL"))) { + index = pos - irc->sasl_mechs->str; + g_string_erase(irc->sasl_mechs, index, strlen("EXTERNAL")); + /* Remove space which separated this mech from the next */ + if ((irc->sasl_mechs->str)[index] == ' ') { + g_string_erase(irc->sasl_mechs, index, 1); irc_auth_start_cyrus(irc);
--- a/libpurple/protocols/jabber/Makefile.am Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/protocols/jabber/Makefile.am Sun Oct 30 12:03:44 2016 +0300
@@ -1,7 +1,5 @@
pkgdir = @PURPLE_PLUGINDIR@
@@ -105,10 +103,6 @@
JABBERSOURCES += auth_cyrus.c
-JABBERSOURCES += win32/posix.uname.c
st = -DPURPLE_STATIC_PRPL
--- a/libpurple/protocols/jabber/Makefile.mingw Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/protocols/jabber/Makefile.mingw Sun Oct 30 12:03:44 2016 +0300
@@ -24,7 +24,6 @@
-I$(GTK_TOP)/include/glib-2.0 \
-I$(GTK_TOP)/lib/glib-2.0/include \
@@ -95,7 +94,6 @@
OBJECTS = $(C_SRC:%.c=%.o)
--- a/libpurple/protocols/jabber/iq.c Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/protocols/jabber/iq.c Sun Oct 30 12:03:44 2016 +0300
@@ -42,10 +42,6 @@
-#include "win32/utsname.h"
static GHashTable *iq_handlers = NULL;
static GHashTable *signal_iq_handlers = NULL;
@@ -232,16 +228,6 @@
if(type == JABBER_IQ_GET) {
const char *ui_name = NULL, *ui_version = NULL;
- if(!purple_prefs_get_bool("/plugins/prpl/jabber/hide_os")) {
- os = g_strdup_printf("%s %s %s", osinfo.sysname, osinfo.release,
iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "jabber:iq:version");
@@ -267,13 +253,6 @@
purple_xmlnode_insert_data(purple_xmlnode_new_child(query, "version"), VERSION, -1);
- purple_xmlnode_insert_data(purple_xmlnode_new_child(query, "os"), os, -1);
--- a/libpurple/protocols/jabber/win32/posix.uname.c Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,141 +0,0 @@
- posix.uname.c - version 1.1
- Copyright (C) 1999, 2000
- Earnie Boyd and assigns
- Fills the utsname structure with the appropriate values.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1, or (at your option)
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICUALR PURPOSE. See the
- GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
- Send bug reports to Earnie Boyd <earnie_boyd@yahoo.com>
-/* ANONYMOUS unions and structs are used from the windows header definitions.
- These need to be defined for them to work correctly with gcc2.95.2-mingw. */
-/*#define _ANONYMOUS_STRUCT*/
-/*#define _ANONYMOUS_UNION*/
-jabber_win32_uname( struct utsname *uts )
- OSVERSIONINFO OS_version;
- SYSTEM_INFO System_Info;
-/* XXX Should these be in the global runtime */
- enum WinOS {Win95, Win98, WinNT, unknown};
- memset( uts, 0, sizeof ( *uts ) );
- OS_version.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
- GetVersionEx ( &OS_version );
- GetSystemInfo ( &System_Info );
- g_strlcpy( uts->sysname, "WIN32_" , sizeof(uts->sysname));
- switch( OS_version.dwPlatformId )
- case VER_PLATFORM_WIN32_NT:
- g_strlcat( uts->sysname, "WinNT", sizeof(uts->sysname) );
- case VER_PLATFORM_WIN32_WINDOWS:
- switch ( OS_version.dwMinorVersion )
- g_strlcat( uts->sysname, "Win95", sizeof(uts->sysname) );
- g_strlcat( uts->sysname, "Win98", sizeof(uts->sysname) );
- g_strlcat( uts->sysname, "Win??", sizeof(uts->sysname) );
- g_strlcat( uts->sysname, "Win??", sizeof(uts->sysname) );
- sprintf( uts->version, "%i", __MINGW32_MAJOR_VERSION );
- sprintf( uts->release, "%i", __MINGW32_MINOR_VERSION );
- switch( System_Info.wProcessorArchitecture )
- case PROCESSOR_ARCHITECTURE_PPC:
- g_strlcpy( uts->machine, "ppc" , sizeof( uts->machine ) );
- case PROCESSOR_ARCHITECTURE_ALPHA:
- g_strlcpy( uts->machine, "alpha" , sizeof( uts->machine ) );
- case PROCESSOR_ARCHITECTURE_MIPS:
- g_strlcpy( uts->machine, "mips" , sizeof( uts->machine ) );
- case PROCESSOR_ARCHITECTURE_INTEL:
- /* dwProcessorType is only valid in Win95 and Win98
- wProcessorLevel is only valid in WinNT */
- switch( System_Info.dwProcessorType )
- case PROCESSOR_INTEL_386:
- case PROCESSOR_INTEL_486:
- case PROCESSOR_INTEL_PENTIUM:
- sprintf( uts->machine, "i%ld", System_Info.dwProcessorType );
- g_strlcpy( uts->machine, "i386" , sizeof( uts->machine ) );
- sprintf( uts->machine, "i%d86", System_Info.wProcessorLevel );
- g_strlcpy( uts->machine, "unknown" , sizeof( uts->machine ) );
- g_strlcpy( uts->machine, "unknown" , sizeof( uts->machine ) );
- sLength = sizeof ( uts->nodename ) - 1;
- GetComputerNameA( uts->nodename, &sLength );
--- a/libpurple/protocols/jabber/win32/utsname.h Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-int jabber_win32_uname (struct utsname *);
-#define uname(utsname) jabber_win32_uname(utsname)
--- a/libpurple/protocols/yahoo/Makefile.am Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/protocols/yahoo/Makefile.am Sun Oct 30 12:03:44 2016 +0300
@@ -1,6 +1,7 @@
pkgdir = @PURPLE_PLUGINDIR@
--- a/libpurple/purple-client-example.c Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/purple-client-example.c Sun Oct 30 12:03:44 2016 +0300
@@ -1,3 +1,25 @@
+ * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA #ifndef DBUS_API_SUBJECT_TO_CHANGE
#define DBUS_API_SUBJECT_TO_CHANGE
--- a/libpurple/purple-client.c Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/purple-client.c Sun Oct 30 12:03:44 2016 +0300
@@ -1,3 +1,25 @@
+ * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA #ifndef DBUS_API_SUBJECT_TO_CHANGE
#define DBUS_API_SUBJECT_TO_CHANGE
--- a/libpurple/purple-client.h Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/purple-client.h Sun Oct 30 12:03:44 2016 +0300
@@ -1,3 +1,25 @@
+ * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA #ifndef _PURPLE_CLIENT_H_INCLUDED_
#define _PURPLE_CLIENT_H_INCLUDED_
--- a/libpurple/purple-gio.c Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/purple-gio.c Sun Oct 30 12:03:44 2016 +0300
@@ -48,9 +48,8 @@
/* Finally can gracefully close */
- /* Close wrapper input stream, if any */
- if (data->input != NULL &&
- !g_input_stream_close(data->input, NULL, &error)) {
+ /* Close input stream, from wrapper or GIOStream */ + if (!g_input_stream_close(data->input, NULL, &error)) { purple_debug_warning("gio",
"Error closing input stream: %s",
@@ -59,9 +58,8 @@
g_clear_object(&data->input);
- /* Close wrapper output stream, if any */
- if (data->output != NULL &&
- !g_output_stream_close(data->output, NULL, &error)) {
+ /* Close output stream, from wrapper or GIOStream */ + if (!g_output_stream_close(data->output, NULL, &error)) { purple_debug_warning("gio",
"Error closing output stream: %s",
@@ -97,7 +95,13 @@
data = g_new(GracefulCloseData, 1);
data->stream = g_object_ref(stream);
+ input = g_io_stream_get_input_stream(stream); data->input = g_object_ref(input);
+ output = g_io_stream_get_output_stream(stream); data->output = g_object_ref(output);
/* Try gracefully closing the stream synchronously */
--- a/libpurple/purple-socket.c Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,410 +0,0 @@
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-#include "purple-socket.h"
- PURPLE_SOCKET_STATE_DISCONNECTED = 0,
- PURPLE_SOCKET_STATE_CONNECTING,
- PURPLE_SOCKET_STATE_CONNECTED,
- PURPLE_SOCKET_STATE_ERROR
- PurpleSocketState state;
- PurpleSslConnection *tls_connection;
- PurpleProxyConnectData *raw_connection;
- PurpleSocketConnectCb cb;
-static GHashTable *handles = NULL;
-handle_add(PurpleSocket *ps)
- PurpleConnection *gc = ps->gc;
- l = g_hash_table_lookup(handles, gc);
- l = g_slist_prepend(l, ps);
- g_hash_table_insert(handles, gc, l);
-handle_remove(PurpleSocket *ps)
- PurpleConnection *gc = ps->gc;
- l = g_hash_table_lookup(handles, gc);
- l = g_slist_remove(l, ps);
- g_hash_table_insert(handles, gc, l);
-_purple_socket_init(void)
- handles = g_hash_table_new(g_direct_hash, g_direct_equal);
-_purple_socket_uninit(void)
- g_hash_table_destroy(handles);
-purple_socket_new(PurpleConnection *gc)
- PurpleSocket *ps = g_new0(PurpleSocket, 1);
- ps->data = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
-purple_socket_get_connection(PurpleSocket *ps)
- g_return_val_if_fail(ps != NULL, NULL);
-purple_socket_check_state(PurpleSocket *ps, PurpleSocketState wanted_state)
- g_return_val_if_fail(ps != NULL, FALSE);
- if (ps->state == wanted_state)
- purple_debug_error("socket", "invalid state: %d (should be: %d)",
- ps->state, wanted_state);
- ps->state = PURPLE_SOCKET_STATE_ERROR;
-purple_socket_set_tls(PurpleSocket *ps, gboolean is_tls)
- g_return_if_fail(ps != NULL);
- if (!purple_socket_check_state(ps, PURPLE_SOCKET_STATE_DISCONNECTED))
-purple_socket_set_host(PurpleSocket *ps, const gchar *host)
- g_return_if_fail(ps != NULL);
- if (!purple_socket_check_state(ps, PURPLE_SOCKET_STATE_DISCONNECTED))
- ps->host = g_strdup(host);
-purple_socket_set_port(PurpleSocket *ps, int port)
- g_return_if_fail(ps != NULL);
- g_return_if_fail(port >= 0);
- g_return_if_fail(port <= 65535);
- if (!purple_socket_check_state(ps, PURPLE_SOCKET_STATE_DISCONNECTED))
-_purple_socket_connected_raw(gpointer _ps, gint fd, const gchar *error_message)
- PurpleSocket *ps = _ps;
- ps->raw_connection = NULL;
- if (!purple_socket_check_state(ps, PURPLE_SOCKET_STATE_CONNECTING)) {
- ps->cb(ps, _("Invalid socket state"), ps->cb_data);
- if (fd <= 0 || error_message != NULL) {
- if (error_message == NULL)
- error_message = _("Unknown error");
- ps->state = PURPLE_SOCKET_STATE_ERROR;
- ps->cb(ps, error_message, ps->cb_data);
- ps->state = PURPLE_SOCKET_STATE_CONNECTED;
- ps->cb(ps, NULL, ps->cb_data);
-_purple_socket_connected_tls(gpointer _ps, PurpleSslConnection *tls_connection,
- PurpleInputCondition cond)
- PurpleSocket *ps = _ps;
- if (!purple_socket_check_state(ps, PURPLE_SOCKET_STATE_CONNECTING)) {
- purple_ssl_close(tls_connection);
- ps->tls_connection = NULL;
- ps->cb(ps, _("Invalid socket state"), ps->cb_data);
- if (ps->tls_connection->fd <= 0) {
- ps->state = PURPLE_SOCKET_STATE_ERROR;
- purple_ssl_close(tls_connection);
- ps->tls_connection = NULL;
- ps->cb(ps, _("Invalid file descriptor"), ps->cb_data);
- ps->state = PURPLE_SOCKET_STATE_CONNECTED;
- ps->fd = ps->tls_connection->fd;
- ps->cb(ps, NULL, ps->cb_data);
-_purple_socket_connected_tls_error(PurpleSslConnection *ssl_connection,
- PurpleSslErrorType error, gpointer _ps)
- PurpleSocket *ps = _ps;
- ps->state = PURPLE_SOCKET_STATE_ERROR;
- ps->tls_connection = NULL;
- ps->cb(ps, purple_ssl_strerror(error), ps->cb_data);
-purple_socket_connect(PurpleSocket *ps, PurpleSocketConnectCb cb,
- PurpleAccount *account = NULL;
- g_return_val_if_fail(ps != NULL, FALSE);
- if (ps->gc && purple_connection_is_disconnecting(ps->gc)) {
- purple_debug_error("socket", "connection is being destroyed");
- ps->state = PURPLE_SOCKET_STATE_ERROR;
- if (!purple_socket_check_state(ps, PURPLE_SOCKET_STATE_DISCONNECTED))
- ps->state = PURPLE_SOCKET_STATE_CONNECTING;
- if (ps->host == NULL || ps->port < 0) {
- purple_debug_error("socket", "Host or port is not specified");
- ps->state = PURPLE_SOCKET_STATE_ERROR;
- account = purple_connection_get_account(ps->gc);
- ps->cb_data = user_data;
- ps->tls_connection = purple_ssl_connect(account, ps->host,
- ps->port, _purple_socket_connected_tls,
- _purple_socket_connected_tls_error, ps);
- ps->raw_connection = purple_proxy_connect(ps->gc, account,
- ps->host, ps->port, _purple_socket_connected_raw, ps);
- if (ps->tls_connection == NULL &&
- ps->raw_connection == NULL)
- ps->state = PURPLE_SOCKET_STATE_ERROR;
-purple_socket_read(PurpleSocket *ps, guchar *buf, size_t len)
- g_return_val_if_fail(ps != NULL, -1);
- g_return_val_if_fail(buf != NULL, -1);
- if (!purple_socket_check_state(ps, PURPLE_SOCKET_STATE_CONNECTED))
- return purple_ssl_read(ps->tls_connection, buf, len);
- return read(ps->fd, buf, len);
-purple_socket_write(PurpleSocket *ps, const guchar *buf, size_t len)
- g_return_val_if_fail(ps != NULL, -1);
- g_return_val_if_fail(buf != NULL, -1);
- if (!purple_socket_check_state(ps, PURPLE_SOCKET_STATE_CONNECTED))
- return purple_ssl_write(ps->tls_connection, buf, len);
- return write(ps->fd, buf, len);
-purple_socket_watch(PurpleSocket *ps, PurpleInputCondition cond,
- PurpleInputFunction func, gpointer user_data)
- g_return_if_fail(ps != NULL);
- if (!purple_socket_check_state(ps, PURPLE_SOCKET_STATE_CONNECTED))
- purple_input_remove(ps->inpa);
- g_return_if_fail(ps->fd > 0);
- ps->inpa = purple_input_add(ps->fd, cond, func, user_data);
-purple_socket_get_fd(PurpleSocket *ps)
- g_return_val_if_fail(ps != NULL, -1);
- if (!purple_socket_check_state(ps, PURPLE_SOCKET_STATE_CONNECTED))
- g_return_val_if_fail(ps->fd > 0, -1);
-purple_socket_set_data(PurpleSocket *ps, const gchar *key, gpointer data)
- g_return_if_fail(ps != NULL);
- g_return_if_fail(key != NULL);
- g_hash_table_remove(ps->data, key);
- g_hash_table_insert(ps->data, g_strdup(key), data);
-purple_socket_get_data(PurpleSocket *ps, const gchar *key)
- g_return_val_if_fail(ps != NULL, NULL);
- g_return_val_if_fail(key != NULL, NULL);
- return g_hash_table_lookup(ps->data, key);
-purple_socket_cancel(PurpleSocket *ps)
- purple_input_remove(ps->inpa);
- if (ps->tls_connection != NULL) {
- purple_ssl_close(ps->tls_connection);
- ps->tls_connection = NULL;
- if (ps->raw_connection != NULL)
- purple_proxy_connect_cancel(ps->raw_connection);
- ps->raw_connection = NULL;
-purple_socket_destroy(PurpleSocket *ps)
- purple_socket_cancel(ps);
- g_hash_table_destroy(ps->data);
-_purple_socket_cancel_with_connection(PurpleConnection *gc)
- it = g_hash_table_lookup(handles, gc);
- for (; it; it = g_slist_next(it)) {
- PurpleSocket *ps = it->data;
- purple_socket_cancel(ps);
--- a/libpurple/purple-socket.h Wed Oct 26 10:17:10 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,217 +0,0 @@
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-#ifndef _PURPLE_SOCKET_H_
-#define _PURPLE_SOCKET_H_
- * SECTION:purple-socket
- * @section_id: libpurple-purple-socket
- * @short_description: <filename>purple-socket.h</filename>
- * @title: Generic Sockets
- * A structure holding all resources needed for the TCP connection.
-typedef struct _PurpleSocket PurpleSocket;
- * PurpleSocketConnectCb:
- * @error: Error message, or NULL if connection was successful.
- * @user_data: The user data passed with callback function.
- * A callback fired after (successfully or not) establishing a connection.
-typedef void (*PurpleSocketConnectCb)(PurpleSocket *ps, const gchar *error,
- * @gc: The connection for which the socket is needed, or NULL.
- * Creates new, disconnected socket.
- * Passing a PurpleConnection allows for proper proxy handling.
- * Returns: The new socket struct.
-purple_socket_new(PurpleConnection *gc);
- * purple_socket_get_connection:
- * Gets PurpleConnection tied with specified socket.
- * Returns: The PurpleConnection object.
-purple_socket_get_connection(PurpleSocket *ps);
- * purple_socket_set_tls:
- * @is_tls: TRUE, if TLS should be handled transparently, FALSE otherwise.
- * Determines, if socket should handle TLS.
-purple_socket_set_tls(PurpleSocket *ps, gboolean is_tls);
- * purple_socket_set_host:
- * @host: The connection host.
- * Sets connection host.
-purple_socket_set_host(PurpleSocket *ps, const gchar *host);
- * purple_socket_set_port:
- * @port: The connection port.
- * Sets connection port.
-purple_socket_set_port(PurpleSocket *ps, int port);
- * purple_socket_connect:
- * @cb: The function to call after establishing a connection, or on
- * @user_data: The user data to be passed to callback function.
- * Establishes a connection.
- * Returns: TRUE on success (this doesn't mean it's connected yet), FALSE
-purple_socket_connect(PurpleSocket *ps, PurpleSocketConnectCb cb,
- * @buf: The buffer to write data to.
- * @len: The buffer size.
- * Reads incoming data from socket.
- * This function deals with TLS, if the socket is configured to do it.
- * Returns: Amount of data written, or -1 on error (errno will be also be set).
-purple_socket_read(PurpleSocket *ps, guchar *buf, size_t len);
- * @buf: The buffer to read data from.
- * @len: The amount of data to read and send.
- * Sends data through socket.
- * This function deals with TLS, if the socket is configured to do it.
- * Returns: Amount of data sent, or -1 on error (errno will albo be set).
-purple_socket_write(PurpleSocket *ps, const guchar *buf, size_t len);
- * @cond: The condition type.
- * @func: The callback function for data, or NULL to remove any
- * @user_data: The user data to be passed to callback function.
- * Adds an input handler for the socket.
- * If the specified socket had input handler already registered, it will be
- * removed. To remove any input handlers, pass an NULL handler function.
-purple_socket_watch(PurpleSocket *ps, PurpleInputCondition cond,
- PurpleInputFunction func, gpointer user_data);
- * purple_socket_get_fd:
- * Gets underlying file descriptor for socket.
- * It's not meant to read/write data (use purple_socket_read/
- * purple_socket_write), rather for watching for changes with select().
- * Returns: The file descriptor, or -1 on error.
-purple_socket_get_fd(PurpleSocket *ps);
- * purple_socket_set_data:
- * @key: The unique key.
- * @data: The data to assign, or NULL to remove.
- * Sets extra data for a socket.
-purple_socket_set_data(PurpleSocket *ps, const gchar *key, gpointer data);
- * purple_socket_get_data:
- * @key: The unqiue key.
- * Returns extra data in a socket.
- * Returns: The data associated with the key.
-purple_socket_get_data(PurpleSocket *ps, const gchar *key);
- * purple_socket_destroy:
- * Destroys the socket, closes connection and frees all resources.
- * If file descriptor for the socket was extracted with purple_socket_get_fd and
- * added to event loop, it have to be removed prior this.
-purple_socket_destroy(PurpleSocket *ps);
-#endif /* _PURPLE_SOCKET_H_ */
--- a/libpurple/tests/test_des.c Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/tests/test_des.c Sun Oct 30 12:03:44 2016 +0300
@@ -1,3 +1,25 @@
+ * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA --- a/libpurple/tests/test_des3.c Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/tests/test_des3.c Sun Oct 30 12:03:44 2016 +0300
@@ -1,3 +1,25 @@
+ * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA --- a/libpurple/tests/test_hmac.c Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/tests/test_hmac.c Sun Oct 30 12:03:44 2016 +0300
@@ -1,3 +1,25 @@
+ * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA --- a/libpurple/tests/test_md4.c Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/tests/test_md4.c Sun Oct 30 12:03:44 2016 +0300
@@ -1,3 +1,25 @@
+ * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA --- a/libpurple/tests/test_md5.c Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/tests/test_md5.c Sun Oct 30 12:03:44 2016 +0300
@@ -1,3 +1,25 @@
+ * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA --- a/libpurple/tests/test_sha1.c Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/tests/test_sha1.c Sun Oct 30 12:03:44 2016 +0300
@@ -1,3 +1,25 @@
+ * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA --- a/libpurple/tests/test_sha256.c Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/tests/test_sha256.c Sun Oct 30 12:03:44 2016 +0300
@@ -1,3 +1,25 @@
+ * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA --- a/libpurple/tests/test_util.c Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/tests/test_util.c Sun Oct 30 12:03:44 2016 +0300
@@ -1,3 +1,25 @@
+ * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA --- a/libpurple/tests/test_xmlnode.c Wed Oct 26 10:17:10 2016 +0000
+++ b/libpurple/tests/test_xmlnode.c Sun Oct 30 12:03:44 2016 +0300
@@ -1,3 +1,25 @@
+ * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA --- a/pidgin/data/pidgin-3-uninstalled.pc.in Wed Oct 26 10:17:10 2016 +0000
+++ b/pidgin/data/pidgin-3-uninstalled.pc.in Sun Oct 30 12:03:44 2016 +0300
@@ -15,7 +15,7 @@
plugindir=${libdir}/pidgin
-Description: Pidgin is a GTK2-based instant messenger application.
+Description: Pidgin is a GTK3-based instant messenger application. -Requires: gtk+-2.0 purple-3
+Requires: gtk+-3.0 webkitgtk-3.0 purple-3 Cflags: -I${abs_top_srcdir}
--- a/pidgin/gtkutils.c Wed Oct 26 10:17:10 2016 +0000
+++ b/pidgin/gtkutils.c Sun Oct 30 12:03:44 2016 +0300
@@ -1189,20 +1189,12 @@
gint space_left, space_right, space_above, space_below;
g_return_if_fail(GTK_IS_MENU(menu));
widget = GTK_WIDGET(menu);
screen = gtk_widget_get_screen(widget);
- context = gtk_widget_get_style_context(widget);
- gtk_style_context_get(context, gtk_style_context_get_state(context),
- "xthickness", &xthickness,
- "ythickness", &ythickness, NULL);
rtl = (gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL);
@@ -1245,24 +1237,14 @@
/* position horizontally */
- /* the amount of space we need to position the menu. Note the
- * menu is offset "xthickness" pixels
- needed_width = requisition.width - xthickness;
- if (needed_width <= space_left ||
- needed_width <= space_right)
+ if (requisition.width <= space_left || + requisition.width <= space_right) - if ((rtl && needed_width <= space_left) ||
- (!rtl && needed_width > space_right))
+ if ((rtl && requisition.width <= space_left) || + (!rtl && requisition.width > space_right)) - *x = *x + xthickness - requisition.width + 1;
+ *x = *x - requisition.width + 1; /* x is clamped on-screen further down */
@@ -1301,20 +1283,19 @@
/* Position vertically. The algorithm is the same as above, but
* simpler because we don't have to take RTL into account.
- needed_height = requisition.height - ythickness;
- if (needed_height <= space_above ||
- needed_height <= space_below)
+ if (requisition.height <= space_above || + requisition.height <= space_below) - if (needed_height <= space_below)
- *y = *y + ythickness - requisition.height + 1;
+ if (requisition.height > space_below) { + *y = *y - requisition.height + 1; *y = CLAMP (*y, monitor.y,
monitor.y + monitor.height - requisition.height);
- else if (needed_height > space_below && needed_height > space_above)
+ else if (requisition.height > space_below && + requisition.height > space_above) if (space_below >= space_above)
*y = monitor.y + monitor.height - requisition.height;
@@ -1340,18 +1321,13 @@
- GtkStyleContext *context;
- context = gtk_widget_get_style_context(GTK_WIDGET(menu));
- gtk_style_context_get(context, gtk_style_context_get_state(context),
- "ythickness", &ythickness, NULL);
gdk_window_get_origin (gtk_widget_get_window(widget), x, y);
gtk_tree_view_get_cursor (tv, &path, &col);
gtk_tree_view_get_cell_area (tv, path, col, &rect);
- *y += rect.y+rect.height+ythickness;
+ *y += rect.y + rect.height; pidgin_menu_position_func_helper(menu, x, y, push_in, data);
--- a/pidgin/gtkwebviewtoolbar.c Wed Oct 26 10:17:10 2016 +0000
+++ b/pidgin/gtkwebviewtoolbar.c Sun Oct 30 12:03:44 2016 +0300
@@ -1197,17 +1197,10 @@
GtkWidget *widget = GTK_WIDGET(data);
- GtkRequisition menu_req;
GtkAllocation allocation;
- GtkStyleContext *context;
- context = gtk_widget_get_style_context(widget);
- gtk_style_context_get(context, gtk_style_context_get_state(context),
- "ythickness", &ythickness, NULL);
gtk_widget_get_allocation(widget, &allocation);
- gtk_widget_get_preferred_size(GTK_WIDGET(menu), NULL, &menu_req);
gdk_window_get_origin(gtk_widget_get_window(widget), x, y);
*y += allocation.y + allocation.height;
@@ -1215,7 +1208,7 @@
pidgin_menu_position_func_helper(menu, x, y, push_in, data);
- if (savy > *y + ythickness + 1)
--- a/pidgin/libpidgin.c Wed Oct 26 10:17:10 2016 +0000
+++ b/pidgin/libpidgin.c Sun Oct 30 12:03:44 2016 +0300
@@ -70,10 +70,13 @@
#include "gtkwhiteboard.h"
* Lists of signals we wish to catch and those we wish to ignore.
@@ -92,6 +95,7 @@
dologin_named(const char *name)
@@ -121,6 +125,7 @@
static char *segfault_message;
static int signal_sockets[2];
@@ -189,6 +194,7 @@
@@ -427,21 +433,23 @@
GtkCssProvider *provider;
int sig_indx; /* for setting up signal catching */
GIOChannel *signal_channel;
guint signal_channel_watcher;
char *segfault_message_tmp;
gboolean debug_enabled, debug_colored;
struct option long_options[] = {
{"config", required_argument, NULL, 'c'},
@@ -474,6 +482,8 @@
/* Locale initialization is not complete here. See gtk_init_check() */
/* We translate this here in case the crash breaks gettext. */
segfault_message_tmp = g_strdup_printf(_(
@@ -574,6 +584,7 @@
snprintf(errmsg, sizeof(errmsg), "Warning: couldn't unblock signals");
/* scan command-line options */
@@ -626,7 +637,9 @@
case '?': /* show terse help */
show_usage(argv[0], TRUE);
g_free(segfault_message);
@@ -635,14 +648,18 @@
show_usage(argv[0], FALSE);
g_free(segfault_message);
/* show version message */
printf("%s %s (libpurple %s)\n", PIDGIN_NAME, DISPLAY_VERSION,
purple_core_get_version());
g_free(segfault_message);
@@ -677,7 +694,9 @@
printf("%s %s\n", PIDGIN_NAME, DISPLAY_VERSION);
g_warning("cannot open display: %s", display ? display : "unset");
g_free(segfault_message);
@@ -711,7 +730,9 @@
"Initialization of the libpurple core failed. Dumping core.\n"
"Please report this!\n");
g_free(segfault_message);
@@ -737,7 +758,9 @@
gdk_notify_startup_complete();
g_printerr(_("Exiting because another libpurple client is already running.\n"));
g_free(segfault_message);
@@ -822,10 +845,12 @@
g_free(segfault_message);
g_source_remove(signal_channel_watcher);
close(signal_sockets[0]);
close(signal_sockets[1]);
--- a/po/POTFILES.in Wed Oct 26 10:17:10 2016 +0000
+++ b/po/POTFILES.in Sun Oct 30 12:03:44 2016 +0300
@@ -191,7 +191,6 @@
libpurple/protocols/yahoo/ymsg.c
libpurple/protocols/zephyr/zephyr.c
-libpurple/purple-socket.c
libpurple/savedstatuses.c
--- a/po/POTFILES.skip Wed Oct 26 10:17:10 2016 +0000
+++ b/po/POTFILES.skip Sun Oct 30 12:03:44 2016 +0300
@@ -69,6 +69,7 @@
pidgin/plugins/perl/common/GtkThemes.c
pidgin/plugins/perl/common/GtkUtils.c
pidgin/plugins/perl/common/Pidgin.c
+sub/libpurple/data/purple-url-handler.desktop.in sub/libpurple/plugins/perl/common/Account.c
sub/libpurple/plugins/perl/common/AccountOpts.c
sub/libpurple/plugins/perl/common/BuddyIcon.c