summaryrefslogtreecommitdiff
path: root/protocols/Gadu-Gadu/src/libgadu/deflate.cpp
diff options
context:
space:
mode:
authorGoraf <22941576+Goraf@users.noreply.github.com>2018-01-18 17:57:36 +0100
committerGoraf <22941576+Goraf@users.noreply.github.com>2018-01-19 01:39:33 +0100
commitfb40ed2b6385b9e3a85b35ba27f3a42207d22234 (patch)
tree9de6415c9c28c68d2fe750abe2c95c3a89ba08ca /protocols/Gadu-Gadu/src/libgadu/deflate.cpp
parent97bb7e79c15952e7f9bf47caef4e3c09dd63c8df (diff)
Gadu-Gadu: update libgadu to 1.11.4
Diffstat (limited to 'protocols/Gadu-Gadu/src/libgadu/deflate.cpp')
-rw-r--r--protocols/Gadu-Gadu/src/libgadu/deflate.cpp226
1 files changed, 226 insertions, 0 deletions
diff --git a/protocols/Gadu-Gadu/src/libgadu/deflate.cpp b/protocols/Gadu-Gadu/src/libgadu/deflate.cpp
new file mode 100644
index 0000000000..46f36f1e69
--- /dev/null
+++ b/protocols/Gadu-Gadu/src/libgadu/deflate.cpp
@@ -0,0 +1,226 @@
+/* $Id$ */
+
+/*
+ * (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,
+ * USA.
+ */
+
+/**
+ * \file deflate.c
+ *
+ * \brief Funkcje kompresji Deflate
+ */
+
+#ifndef _WIN64
+#define _USE_32BIT_TIME_T
+#endif
+
+#ifdef _WIN32
+#include "win32.h"
+#endif /* _WIN32 */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "libgadu.h"
+#include "deflate.h"
+
+#ifdef GG_CONFIG_HAVE_ZLIB
+#include <zlib.h>
+#endif
+
+/**
+ * \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
+ int ret;
+ z_stream strm;
+ unsigned char *out, *out2;
+ size_t out_len;
+
+ if (in == NULL || out_lenp == NULL)
+ return NULL;
+
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+ strm.avail_in = strlen(in);
+ strm.next_in = (unsigned char*) in;
+
+ ret = deflateInit(&strm, Z_BEST_COMPRESSION);
+ if (ret != Z_OK) {
+ gg_debug(GG_DEBUG_MISC, "// gg_deflate() deflateInit() failed (%d)\n", ret);
+ return NULL;
+ }
+
+ out_len = deflateBound(&strm, strm.avail_in);
+ out = (unsigned char*)malloc(out_len);
+
+ if (out == NULL) {
+ gg_debug(GG_DEBUG_MISC, "// gg_deflate() not enough memory for output data (%d)\n", out_len);
+ goto fail;
+ }
+
+ strm.avail_out = out_len;
+ strm.next_out = out;
+
+ for (;;) {
+ ret = deflate(&strm, Z_FINISH);
+
+ if (ret == Z_STREAM_END)
+ break;
+
+ /* raczej nie powinno się zdarzyć przy Z_FINISH i out_len == deflateBound(),
+ * ale dokumentacja zlib nie wyklucza takiej możliwości */
+ if (ret == Z_OK) {
+ out_len *= 2;
+ out2 = (unsigned char*)realloc(out, out_len);
+
+ if (out2 == NULL) {
+ gg_debug(GG_DEBUG_MISC, "// gg_deflate() not enough memory for output data (%d)\n", out_len);
+ goto fail;
+ }
+
+ out = out2;
+
+ strm.avail_out = out_len / 2;
+ strm.next_out = out + out_len / 2;
+ } else {
+ gg_debug(GG_DEBUG_MISC, "// gg_deflate() deflate() failed (ret=%d, msg=%s)\n", ret, strm.msg != NULL ? strm.msg : "no error message provided");
+ goto fail;
+ }
+ }
+
+ out_len = strm.total_out;
+ out2 = (unsigned char*)realloc(out, out_len);
+
+ if (out2 == NULL) {
+ gg_debug(GG_DEBUG_MISC, "// gg_deflate() not enough memory for output data (%d)\n", out_len);
+ goto fail;
+ }
+
+ *out_lenp = out_len;
+ deflateEnd(&strm);
+
+ return out2;
+
+fail:
+ *out_lenp = 0;
+ deflateEnd(&strm);
+ free(out);
+#endif
+ return NULL;
+}
+
+/**
+ * \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
+ int ret;
+ z_stream strm;
+ char *out = NULL, *out2;
+ size_t out_len = 1024;
+ int first = 1;
+
+ if (in == NULL)
+ return NULL;
+
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+ strm.avail_in = length;
+ strm.next_in = (unsigned char*) in;
+
+ ret = inflateInit(&strm);
+ if (ret != Z_OK) {
+ gg_debug(GG_DEBUG_MISC, "// gg_inflate() inflateInit() failed (%d)\n", ret);
+ return NULL;
+ }
+
+ do {
+ out_len *= 2;
+ out2 = (char*)realloc(out, out_len);
+
+ if (out2 == NULL) {
+ gg_debug(GG_DEBUG_MISC, "// gg_inflate() not enough memory for output data (%d)\n", out_len);
+ goto fail;
+ }
+
+ out = out2;
+
+ if (first) {
+ strm.avail_out = out_len;
+ strm.next_out = (unsigned char*) out;
+ } else {
+ 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");
+ goto fail;
+ }
+
+ first = 0;
+ } while (ret != Z_STREAM_END);
+
+ /* rezerwujemy ostatni znak na NULL-a */
+ out_len = strm.total_out + 1;
+ out2 = (char*)realloc(out, out_len);
+
+ if (out2 == NULL) {
+ gg_debug(GG_DEBUG_MISC, "// gg_inflate() not enough memory for output data (%d)\n", out_len);
+ goto fail;
+ }
+
+ out = out2;
+ out[out_len - 1] = '\0';
+
+ inflateEnd(&strm);
+
+ return out;
+
+fail:
+ inflateEnd(&strm);
+ free(out);
+#endif
+ return NULL;
+}