summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/Makefile.am2
-rw-r--r--src/core/wee-dir.c906
-rw-r--r--src/core/wee-dir.h8
-rw-r--r--src/gui/curses/CMakeLists.txt3
-rw-r--r--src/gui/curses/headless/Makefile.am2
-rw-r--r--src/gui/curses/normal/Makefile.am2
-rw-r--r--src/plugins/plugin.c1
-rw-r--r--src/plugins/weechat-plugin.h8
9 files changed, 611 insertions, 323 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index ca11b685c..78099ecd7 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -88,6 +88,8 @@ include_directories(${GNUTLS_INCLUDE_PATH})
include_directories(${CURL_INCLUDE_DIRS})
+include_directories(${ZSTD_INCLUDE_DIRS})
+
include_directories(${CMAKE_BINARY_DIR})
add_library(weechat_core STATIC ${LIB_CORE_SRC})
target_link_libraries(weechat_core coverage_config)
diff --git a/src/core/Makefile.am b/src/core/Makefile.am
index 6e977a74a..eed6204d2 100644
--- a/src/core/Makefile.am
+++ b/src/core/Makefile.am
@@ -17,7 +17,7 @@
# along with WeeChat. If not, see <https://www.gnu.org/licenses/>.
#
-AM_CPPFLAGS = -DLOCALEDIR=\"$(datadir)/locale\" $(GCRYPT_CFLAGS) $(GNUTLS_CFLAGS) $(CURL_CFLAGS)
+AM_CPPFLAGS = -DLOCALEDIR=\"$(datadir)/locale\" $(GCRYPT_CFLAGS) $(GNUTLS_CFLAGS) $(CURL_CFLAGS) $(ZLIB_CFLAGS) $(ZSTD_CFLAGS)
noinst_LIBRARIES = lib_weechat_core.a
diff --git a/src/core/wee-dir.c b/src/core/wee-dir.c
index 7a0b702e0..32a607f34 100644
--- a/src/core/wee-dir.c
+++ b/src/core/wee-dir.c
@@ -44,6 +44,8 @@
#include <unistd.h>
#include <dirent.h>
#include <ftw.h>
+#include <zlib.h>
+#include <zstd.h>
#include "weechat.h"
#include "wee-config.h"
@@ -294,324 +296,6 @@ dir_rmtree (const char *directory)
}
/*
- * Finds files in a directory and executes a function on each file.
- */
-
-void
-dir_exec_on_files (const char *directory, int recurse_subdirs,
- int hidden_files,
- void (*callback)(void *data, const char *filename),
- void *callback_data)
-{
- char complete_filename[PATH_MAX];
- DIR *dir;
- struct dirent *entry;
- struct stat statbuf;
-
- if (!directory || !callback)
- return;
-
- dir = opendir (directory);
- if (dir)
- {
- while ((entry = readdir (dir)))
- {
- if (hidden_files || (entry->d_name[0] != '.'))
- {
- snprintf (complete_filename, sizeof (complete_filename),
- "%s/%s", directory, entry->d_name);
- lstat (complete_filename, &statbuf);
- if (S_ISDIR(statbuf.st_mode))
- {
- if (recurse_subdirs
- && (strcmp (entry->d_name, ".") != 0)
- && (strcmp (entry->d_name, "..") != 0))
- {
- dir_exec_on_files (complete_filename, 1, hidden_files,
- callback, callback_data);
- }
- }
- else
- {
- (*callback) (callback_data, complete_filename);
- }
- }
- }
- closedir (dir);
- }
-}
-
-/*
- * Searches for the full name of a WeeChat library with name and extension
- * (searches first in WeeChat user's dir, then WeeChat global lib directory).
- *
- * Returns name of library found, NULL if not found.
- *
- * Note: result must be freed after use (if not NULL).
- */
-
-char *
-dir_search_full_lib_name_ext (const char *filename, const char *extension,
- const char *plugins_dir)
-{
- char *name_with_ext, *final_name, *extra_libdir;
- int length;
- struct stat st;
-
- length = strlen (filename) + strlen (extension) + 1;
- name_with_ext = malloc (length);
- if (!name_with_ext)
- return NULL;
- snprintf (name_with_ext, length,
- "%s%s",
- filename,
- (strchr (filename, '.')) ? "" : extension);
-
- /* try libdir from environment variable WEECHAT_EXTRA_LIBDIR */
- extra_libdir = getenv (WEECHAT_EXTRA_LIBDIR);
- if (extra_libdir && extra_libdir[0])
- {
- length = strlen (extra_libdir) + strlen (name_with_ext) +
- strlen (plugins_dir) + 16;
- final_name = malloc (length);
- if (!final_name)
- {
- free (name_with_ext);
- return NULL;
- }
- snprintf (final_name, length,
- "%s%s%s%s%s",
- extra_libdir,
- DIR_SEPARATOR,
- plugins_dir,
- DIR_SEPARATOR,
- name_with_ext);
- if ((stat (final_name, &st) == 0) && (st.st_size > 0))
- {
- free (name_with_ext);
- return final_name;
- }
- free (final_name);
- }
-
- /* try WeeChat user's dir */
- length = strlen (weechat_data_dir) + strlen (name_with_ext) +
- strlen (plugins_dir) + 16;
- final_name = malloc (length);
- if (!final_name)
- {
- free (name_with_ext);
- return NULL;
- }
- snprintf (final_name, length,
- "%s%s%s%s%s",
- weechat_data_dir,
- DIR_SEPARATOR,
- plugins_dir,
- DIR_SEPARATOR,
- name_with_ext);
- if ((stat (final_name, &st) == 0) && (st.st_size > 0))
- {
- free (name_with_ext);
- return final_name;
- }
- free (final_name);
-
- /* try WeeChat global lib dir */
- length = strlen (WEECHAT_LIBDIR) + strlen (name_with_ext) +
- strlen (plugins_dir) + 16;
- final_name = malloc (length);
- if (!final_name)
- {
- free (name_with_ext);
- return NULL;
- }
- snprintf (final_name, length,
- "%s%s%s%s%s",
- WEECHAT_LIBDIR,
- DIR_SEPARATOR,
- plugins_dir,
- DIR_SEPARATOR,
- name_with_ext);
- if ((stat (final_name, &st) == 0) && (st.st_size > 0))
- {
- free (name_with_ext);
- return final_name;
- }
- free (final_name);
-
- free (name_with_ext);
-
- return NULL;
-}
-
-/*
- * Searches for the full name of a WeeChat library with name.
- *
- * All extensions listed in option "weechat.plugin.extension" are tested.
- *
- * Note: result must be freed after use (if not NULL).
- */
-
-char *
-dir_search_full_lib_name (const char *filename, const char *plugins_dir)
-{
- char *filename2, *full_name;
- int i;
-
- /* expand home in filename */
- filename2 = string_expand_home (filename);
- if (!filename2)
- return NULL;
-
- /* if full path, return it */
- if (strchr (filename2, '/') || strchr (filename2, '\\'))
- return filename2;
-
- if (config_plugin_extensions)
- {
- for (i = 0; i < config_num_plugin_extensions; i++)
- {
- full_name = dir_search_full_lib_name_ext (
- filename2,
- config_plugin_extensions[i],
- plugins_dir);
- if (full_name)
- {
- free (filename2);
- return full_name;
- }
- }
- }
- else
- {
- full_name = dir_search_full_lib_name_ext (filename2, "", plugins_dir);
- if (full_name)
- {
- free (filename2);
- return full_name;
- }
- }
-
- free (filename2);
-
- return strdup (filename);
-}
-
-/*
- * Reads content of a file.
- *
- * Returns an allocated buffer with the content of file, NULL if error.
- *
- * Note: result must be freed after use.
- */
-
-char *
-dir_file_get_content (const char *filename)
-{
- char *buffer, *buffer2;
- FILE *f;
- size_t count, fp;
-
- if (!filename)
- return NULL;
-
- buffer = NULL;
- fp = 0;
-
- f = fopen (filename, "r");
- if (!f)
- goto error;
-
- while (!feof (f))
- {
- if (fp > SIZE_MAX - (1024 * sizeof (char)))
- goto error;
- buffer2 = (char *) realloc (buffer, (fp + (1024 * sizeof (char))));
- if (!buffer2)
- goto error;
- buffer = buffer2;
- count = fread (&buffer[fp], sizeof (char), 1024, f);
- if (count <= 0)
- goto error;
- fp += count;
- }
- if (fp > SIZE_MAX - sizeof (char))
- goto error;
- buffer2 = (char *) realloc (buffer, fp + sizeof (char));
- if (!buffer2)
- goto error;
- buffer = buffer2;
- buffer[fp] = '\0';
- fclose (f);
-
- return buffer;
-
-error:
- if (buffer)
- free (buffer);
- if (f)
- fclose (f);
- return NULL;
-}
-
-/*
- * Copies a file to another location.
- *
- * Returns:
- * 1: OK
- * 0: error
- */
-
-int
-dir_file_copy (const char *from, const char *to)
-{
- FILE *src, *dst;
- char *buffer;
- int rc;
- size_t count;
-
- rc = 0;
- buffer = NULL;
- src = NULL;
- dst = NULL;
-
- if (!from || !from[0] || !to || !to[0])
- goto end;
-
- buffer = malloc (65536);
- if (!buffer)
- goto end;
-
- src = fopen (from, "rb");
- if (!src)
- goto end;
- dst = fopen (to, "wb");
- if (!dst)
- goto end;
-
- while (!feof (src))
- {
- count = fread (buffer, 1, 65536, src);
- if (count <= 0)
- goto end;
- if (fwrite (buffer, 1, count, dst) <= 0)
- goto end;
- }
-
- rc = 1;
-
-end:
- if (buffer)
- free (buffer);
- if (src)
- fclose (src);
- if (dst)
- fclose (dst);
- return rc;
-}
-
-/*
* Uses one or four different paths for WeeChat home directories.
*
* If 4 paths are given, they must be separated by colons and given in this
@@ -1038,3 +722,589 @@ dir_get_string_home_dirs ()
return string_rebuild_split_string ((const char **)dirs, ":", 0, -1);
}
+
+/*
+ * Finds files in a directory and executes a function on each file.
+ */
+
+void
+dir_exec_on_files (const char *directory, int recurse_subdirs,
+ int hidden_files,
+ void (*callback)(void *data, const char *filename),
+ void *callback_data)
+{
+ char complete_filename[PATH_MAX];
+ DIR *dir;
+ struct dirent *entry;
+ struct stat statbuf;
+
+ if (!directory || !callback)
+ return;
+
+ dir = opendir (directory);
+ if (dir)
+ {
+ while ((entry = readdir (dir)))
+ {
+ if (hidden_files || (entry->d_name[0] != '.'))
+ {
+ snprintf (complete_filename, sizeof (complete_filename),
+ "%s/%s", directory, entry->d_name);
+ lstat (complete_filename, &statbuf);
+ if (S_ISDIR(statbuf.st_mode))
+ {
+ if (recurse_subdirs
+ && (strcmp (entry->d_name, ".") != 0)
+ && (strcmp (entry->d_name, "..") != 0))
+ {
+ dir_exec_on_files (complete_filename, 1, hidden_files,
+ callback, callback_data);
+ }
+ }
+ else
+ {
+ (*callback) (callback_data, complete_filename);
+ }
+ }
+ }
+ closedir (dir);
+ }
+}
+
+/*
+ * Searches for the full name of a WeeChat library with name and extension
+ * (searches first in WeeChat user's dir, then WeeChat global lib directory).
+ *
+ * Returns name of library found, NULL if not found.
+ *
+ * Note: result must be freed after use (if not NULL).
+ */
+
+char *
+dir_search_full_lib_name_ext (const char *filename, const char *extension,
+ const char *plugins_dir)
+{
+ char *name_with_ext, *final_name, *extra_libdir;
+ int length;
+ struct stat st;
+
+ length = strlen (filename) + strlen (extension) + 1;
+ name_with_ext = malloc (length);
+ if (!name_with_ext)
+ return NULL;
+ snprintf (name_with_ext, length,
+ "%s%s",
+ filename,
+ (strchr (filename, '.')) ? "" : extension);
+
+ /* try libdir from environment variable WEECHAT_EXTRA_LIBDIR */
+ extra_libdir = getenv (WEECHAT_EXTRA_LIBDIR);
+ if (extra_libdir && extra_libdir[0])
+ {
+ length = strlen (extra_libdir) + strlen (name_with_ext) +
+ strlen (plugins_dir) + 16;
+ final_name = malloc (length);
+ if (!final_name)
+ {
+ free (name_with_ext);
+ return NULL;
+ }
+ snprintf (final_name, length,
+ "%s%s%s%s%s",
+ extra_libdir,
+ DIR_SEPARATOR,
+ plugins_dir,
+ DIR_SEPARATOR,
+ name_with_ext);
+ if ((stat (final_name, &st) == 0) && (st.st_size > 0))
+ {
+ free (name_with_ext);
+ return final_name;
+ }
+ free (final_name);
+ }
+
+ /* try WeeChat user's dir */
+ length = strlen (weechat_data_dir) + strlen (name_with_ext) +
+ strlen (plugins_dir) + 16;
+ final_name = malloc (length);
+ if (!final_name)
+ {
+ free (name_with_ext);
+ return NULL;
+ }
+ snprintf (final_name, length,
+ "%s%s%s%s%s",
+ weechat_data_dir,
+ DIR_SEPARATOR,
+ plugins_dir,
+ DIR_SEPARATOR,
+ name_with_ext);
+ if ((stat (final_name, &st) == 0) && (st.st_size > 0))
+ {
+ free (name_with_ext);
+ return final_name;
+ }
+ free (final_name);
+
+ /* try WeeChat global lib dir */
+ length = strlen (WEECHAT_LIBDIR) + strlen (name_with_ext) +
+ strlen (plugins_dir) + 16;
+ final_name = malloc (length);
+ if (!final_name)
+ {
+ free (name_with_ext);
+ return NULL;
+ }
+ snprintf (final_name, length,
+ "%s%s%s%s%s",
+ WEECHAT_LIBDIR,
+ DIR_SEPARATOR,
+ plugins_dir,
+ DIR_SEPARATOR,
+ name_with_ext);
+ if ((stat (final_name, &st) == 0) && (st.st_size > 0))
+ {
+ free (name_with_ext);
+ return final_name;
+ }
+ free (final_name);
+
+ free (name_with_ext);
+
+ return NULL;
+}
+
+/*
+ * Searches for the full name of a WeeChat library with name.
+ *
+ * All extensions listed in option "weechat.plugin.extension" are tested.
+ *
+ * Note: result must be freed after use (if not NULL).
+ */
+
+char *
+dir_search_full_lib_name (const char *filename, const char *plugins_dir)
+{
+ char *filename2, *full_name;
+ int i;
+
+ /* expand home in filename */
+ filename2 = string_expand_home (filename);
+ if (!filename2)
+ return NULL;
+
+ /* if full path, return it */
+ if (strchr (filename2, '/') || strchr (filename2, '\\'))
+ return filename2;
+
+ if (config_plugin_extensions)
+ {
+ for (i = 0; i < config_num_plugin_extensions; i++)
+ {
+ full_name = dir_search_full_lib_name_ext (
+ filename2,
+ config_plugin_extensions[i],
+ plugins_dir);
+ if (full_name)
+ {
+ free (filename2);
+ return full_name;
+ }
+ }
+ }
+ else
+ {
+ full_name = dir_search_full_lib_name_ext (filename2, "", plugins_dir);
+ if (full_name)
+ {
+ free (filename2);
+ return full_name;
+ }
+ }
+
+ free (filename2);
+
+ return strdup (filename);
+}
+
+/*
+ * Reads content of a file.
+ *
+ * Returns an allocated buffer with the content of file, NULL if error.
+ *
+ * Note: result must be freed after use.
+ */
+
+char *
+dir_file_get_content (const char *filename)
+{
+ char *buffer, *buffer2;
+ FILE *f;
+ size_t count, fp;
+
+ if (!filename)
+ return NULL;
+
+ buffer = NULL;
+ fp = 0;
+
+ f = fopen (filename, "r");
+ if (!f)
+ goto error;
+
+ while (!feof (f))
+ {
+ if (fp > SIZE_MAX - (1024 * sizeof (char)))
+ goto error;
+ buffer2 = (char *) realloc (buffer, (fp + (1024 * sizeof (char))));
+ if (!buffer2)
+ goto error;
+ buffer = buffer2;
+ count = fread (&buffer[fp], sizeof (char), 1024, f);
+ if (count <= 0)
+ goto error;
+ fp += count;
+ }
+ if (fp > SIZE_MAX - sizeof (char))
+ goto error;
+ buffer2 = (char *) realloc (buffer, fp + sizeof (char));
+ if (!buffer2)
+ goto error;
+ buffer = buffer2;
+ buffer[fp] = '\0';
+ fclose (f);
+
+ return buffer;
+
+error:
+ if (buffer)
+ free (buffer);
+ if (f)
+ fclose (f);
+ return NULL;
+}
+
+/*
+ * Copies a file to another location.
+ *
+ * Returns:
+ * 1: OK
+ * 0: error
+ */
+
+int
+dir_file_copy (const char *from, const char *to)
+{
+ FILE *src, *dst;
+ char *buffer;
+ int rc;
+ size_t count;
+
+ rc = 0;
+ buffer = NULL;
+ src = NULL;
+ dst = NULL;
+
+ if (!from || !from[0] || !to || !to[0])
+ goto end;
+
+ buffer = malloc (65536);
+ if (!buffer)
+ goto end;
+
+ src = fopen (from, "rb");
+ if (!src)
+ goto end;
+ dst = fopen (to, "wb");
+ if (!dst)
+ goto end;
+
+ while (!feof (src))
+ {
+ count = fread (buffer, 1, 65536, src);
+ if (count <= 0)
+ goto end;
+ if (fwrite (buffer, 1, count, dst) <= 0)
+ goto end;
+ }
+
+ rc = 1;
+
+end:
+ if (buffer)
+ free (buffer);
+ if (src)
+ fclose (src);
+ if (dst)
+ fclose (dst);
+ return rc;
+}
+
+/*
+ * Compresses a file with gzip.
+ *
+ * The output file must not exist.
+ *
+ * Returns:
+ * 1: OK
+ * 0: error
+ */
+
+int
+dir_file_compress_gzip (const char *from, const char *to,
+ int compression_level)
+{
+ FILE *source, *dest;
+ z_stream strm;
+ unsigned char *buffer_in, *buffer_out;
+ int rc, ret, flush;
+ size_t buffer_size, have;
+
+ source = NULL;
+ dest = NULL;
+ buffer_size = 256 * 1024;
+ buffer_in = NULL;
+ buffer_out = NULL;
+ rc = 0;
+
+ if (!from || !to || (compression_level < 1) || (compression_level > 9))
+ goto end;
+
+ if (access (to, F_OK) == 0)
+ goto end;
+
+ buffer_in = malloc (buffer_size);
+ if (!buffer_in)
+ goto end;
+ buffer_out = malloc (buffer_size);
+ if (!buffer_out)
+ goto end;
+
+ source = fopen (from, "rb");
+ if (!source)
+ goto end;
+ dest = fopen (to, "wb");
+ if (!dest)
+ goto end;
+
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+
+ ret = deflateInit2 (
+ &strm,
+ compression_level,
+ Z_DEFLATED, /* method */
+ 15 + 16, /* + 16 = gzip instead of zlib */
+ 8, /* memLevel */
+ Z_DEFAULT_STRATEGY); /* strategy */
+ if (ret != Z_OK)
+ goto end;
+
+ do
+ {
+ strm.avail_in = fread (buffer_in, 1, buffer_size, source);
+ if (ferror (source))
+ goto error;
+
+ flush = feof (source) ? Z_FINISH : Z_NO_FLUSH;
+ strm.next_in = buffer_in;
+
+ do
+ {
+ strm.avail_out = buffer_size;
+ strm.next_out = buffer_out;
+ ret = deflate (&strm, flush);
+ if (ret == Z_STREAM_ERROR)
+ goto error;
+ have = buffer_size - strm.avail_out;
+ if (fwrite (buffer_out, 1, have, dest) != have || ferror (dest))
+ goto error;
+ } while (strm.avail_out == 0);
+ if (strm.avail_in != 0)
+ goto error;
+ } while (flush != Z_FINISH);
+
+ if (ret != Z_STREAM_END)
+ goto error;
+
+ (void) deflateEnd (&strm);
+
+ rc = 1;
+ goto end;
+
+error:
+ (void) deflateEnd (&strm);
+ unlink (to);
+
+end:
+ if (buffer_in)
+ free (buffer_in);
+ if (buffer_out)
+ free (buffer_out);
+ if (source)
+ fclose (source);
+ if (dest)
+ fclose (dest);
+
+ return rc;
+}
+
+/*
+ * Compresses a file with zstandard.
+ *
+ * The output file must not exist.
+ *
+ * Returns:
+ * 1: OK
+ * 0: error
+ */
+
+int
+dir_file_compress_zstd (const char *from, const char *to,
+ int compression_level)
+{
+ FILE *source, *dest;
+ void *buffer_in, *buffer_out;
+ size_t buffer_in_size, buffer_out_size, num_read, remaining;
+ int rc, finished, last_chunk;
+ ZSTD_CCtx *cctx;
+ ZSTD_EndDirective mode;
+ ZSTD_inBuffer input;
+ ZSTD_outBuffer output;
+
+ source = NULL;
+ dest = NULL;
+ buffer_in = NULL;
+ buffer_out = NULL;
+ cctx = NULL;
+ rc = 0;
+
+ if (!from || !to || (compression_level < 1) || (compression_level > 19))
+ goto end;
+
+ if (access (to, F_OK) == 0)
+ goto end;
+
+ buffer_in_size = ZSTD_CStreamInSize ();
+ buffer_in = malloc (buffer_in_size);
+ if (!buffer_in)
+ goto end;
+ buffer_out_size = ZSTD_CStreamOutSize ();
+ buffer_out = malloc (buffer_out_size);
+ if (!buffer_out)
+ goto end;
+
+ source = fopen (from, "rb");
+ if (!source)
+ goto end;
+ dest = fopen (to, "wb");
+ if (!dest)
+ goto end;
+
+ cctx = ZSTD_createCCtx ();
+ if (!cctx)
+ goto end;
+
+ ZSTD_CCtx_setParameter (cctx, ZSTD_c_compressionLevel, compression_level);
+
+ while (1)
+ {
+ num_read = fread (buffer_in, 1, buffer_in_size, source);
+ if (ferror (source))
+ goto error;
+ last_chunk = (num_read < buffer_in_size);
+ mode = (last_chunk) ? ZSTD_e_end : ZSTD_e_continue;
+ input.src = buffer_in;
+ input.size = num_read;
+ input.pos = 0;
+ finished = 0;
+ while (!finished)
+ {
+ output.dst = buffer_out;
+ output.size = buffer_out_size;
+ output.pos = 0;
+ remaining = ZSTD_compressStream2(cctx, &output , &input, mode);
+ if (ZSTD_isError (remaining))
+ goto error;
+ fwrite (buffer_out, 1, output.pos, dest);
+ finished = (last_chunk) ? (remaining == 0) : (input.pos == input.size);
+ };
+ if (input.pos != input.size)
+ goto error;
+ if (last_chunk)
+ break;
+ }
+
+ rc = 1;
+ goto end;
+
+error:
+ if (cctx)
+ {
+ ZSTD_freeCCtx (cctx);
+ cctx = NULL;
+ }
+ unlink (to);
+
+end:
+ if (cctx)
+ ZSTD_freeCCtx (cctx);
+ if (buffer_in)
+ free (buffer_in);
+ if (buffer_out)
+ free (buffer_out);
+ if (source)
+ fclose (source);
+ if (dest)
+ fclose (dest);
+
+ return rc;
+}
+
+/*
+ * Compresses a file with gzip or zstandard.
+ *
+ * The output file must not exist.
+ *
+ * Supported values for parameter "compressor":
+ * - "gzip": gzip compression (via zlib)
+ * - "zstd": zstandard compression
+ *
+ * Parameter "compression_level" is the compression level as percentage:
+ * from 1 (fast, low compression) to 100 (slow, best compression).
+ *
+ * Returns:
+ * 1: OK
+ * 0: error
+ */
+
+int
+dir_file_compress (const char *filename_input,
+ const char *filename_output,
+ const char *compressor,
+ int compression_level)
+{
+ int level;
+
+ if (!compressor || (compression_level < 1) || (compression_level > 100))
+ return 0;
+
+ if (strcmp (compressor, "gzip") == 0)
+ {
+ /* convert percent to zlib compression level (1-9) */
+ level = (((compression_level - 1) * 9) / 100) + 1;
+ return dir_file_compress_gzip (filename_input, filename_output, level);
+ }
+ else if (strcmp (compressor, "zstd") == 0)
+ {
+ /* convert percent to zstd compression level (1-19) */
+ level = (((compression_level - 1) * 19) / 100) + 1;
+ return dir_file_compress_zstd (filename_input, filename_output, level);
+ }
+ else
+ {
+ return 0;
+ }
+}
diff --git a/src/core/wee-dir.h b/src/core/wee-dir.h
index 861a68182..b02d31e28 100644
--- a/src/core/wee-dir.h
+++ b/src/core/wee-dir.h
@@ -25,6 +25,9 @@ extern int dir_mkdir_home (const char *directory, int mode);
extern int dir_mkdir (const char *directory, int mode);
extern int dir_mkdir_parents (const char *directory, int mode);
extern int dir_rmtree (const char *directory);
+extern void dir_create_home_dirs ();
+extern void dir_remove_home_dirs ();
+extern char *dir_get_string_home_dirs ();
extern void dir_exec_on_files (const char *directory, int recurse_subdirs,
int hidden_files,
void (*callback)(void *data,
@@ -34,8 +37,7 @@ extern char *dir_search_full_lib_name (const char *filename,
const char *sys_directory);
extern char *dir_file_get_content (const char *filename);
extern int dir_file_copy (const char *from, const char *to);
-extern void dir_create_home_dirs ();
-extern void dir_remove_home_dirs ();
-extern char *dir_get_string_home_dirs ();
+extern int dir_file_compress (const char *from, const char *to,
+ const char *compressor, int compression_level);
#endif /* WEECHAT_DIR_H */
diff --git a/src/gui/curses/CMakeLists.txt b/src/gui/curses/CMakeLists.txt
index 71bb93ab2..27057d53b 100644
--- a/src/gui/curses/CMakeLists.txt
+++ b/src/gui/curses/CMakeLists.txt
@@ -47,6 +47,9 @@ list(APPEND EXTRA_LIBS "m")
list(APPEND EXTRA_LIBS ${CURL_LIBRARIES})
+list(APPEND EXTRA_LIBS ${ZLIB_LIBRARY})
+list(APPEND EXTRA_LIBS ${LIBZSTD_LDFLAGS})
+
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
# link with resolv lib on macOS
list(APPEND EXTRA_LIBS "resolv")
diff --git a/src/gui/curses/headless/Makefile.am b/src/gui/curses/headless/Makefile.am
index 5851d8583..18757c94d 100644
--- a/src/gui/curses/headless/Makefile.am
+++ b/src/gui/curses/headless/Makefile.am
@@ -48,6 +48,8 @@ weechat_headless_LDADD = ./../../../core/lib_weechat_core.a \
$(GCRYPT_LFLAGS) \
$(GNUTLS_LFLAGS) \
$(CURL_LFLAGS) \
+ $(ZLIB_LFLAGS) \
+ $(ZSTD_LFLAGS) \
-lm
weechat_headless_SOURCES = main.c
diff --git a/src/gui/curses/normal/Makefile.am b/src/gui/curses/normal/Makefile.am
index 6936a41a4..df2fb2b58 100644
--- a/src/gui/curses/normal/Makefile.am
+++ b/src/gui/curses/normal/Makefile.am
@@ -45,6 +45,8 @@ weechat_LDADD = ./../../../core/lib_weechat_core.a \
$(GCRYPT_LFLAGS) \
$(GNUTLS_LFLAGS) \
$(CURL_LFLAGS) \
+ $(ZLIB_LFLAGS) \
+ $(ZSTD_LFLAGS) \
-lm
weechat_SOURCES = main.c
diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c
index 3e2471dd2..741876d12 100644
--- a/src/plugins/plugin.c
+++ b/src/plugins/plugin.c
@@ -676,6 +676,7 @@ plugin_load (const char *filename, int init_plugin, int argc, char **argv)
new_plugin->exec_on_files = &dir_exec_on_files;
new_plugin->file_get_content = &dir_file_get_content;
new_plugin->file_copy = &dir_file_copy;
+ new_plugin->file_compress = &dir_file_compress;
new_plugin->util_timeval_cmp = &util_timeval_cmp;
new_plugin->util_timeval_diff = &util_timeval_diff;
diff --git a/src/plugins/weechat-plugin.h b/src/plugins/weechat-plugin.h
index 1bfa9a9dc..a0f6184ad 100644
--- a/src/plugins/weechat-plugin.h
+++ b/src/plugins/weechat-plugin.h
@@ -68,7 +68,7 @@ struct timeval;
* please change the date with current one; for a second change at same
* date, increment the 01, otherwise please keep 01.
*/
-#define WEECHAT_PLUGIN_API_VERSION "20220925-01"
+#define WEECHAT_PLUGIN_API_VERSION "20220926-01"
/* macros for defining plugin infos */
#define WEECHAT_PLUGIN_NAME(__name) \
@@ -402,6 +402,8 @@ struct t_weechat_plugin
void *callback_data);
char *(*file_get_content) (const char *filename);
int (*file_copy) (const char *from, const char *to);
+ int (*file_compress) (const char *from, const char *to,
+ const char *compressor, int compression_level);
/* util */
int (*util_timeval_cmp) (struct timeval *tv1, struct timeval *tv2);
@@ -1415,6 +1417,10 @@ extern int weechat_plugin_end (struct t_weechat_plugin *plugin);
(weechat_plugin->file_get_content)(__filename)
#define weechat_file_copy(__from, __to) \
(weechat_plugin->file_copy)(__from, __to)
+#define weechat_file_compress(__from, __to, __compressor, \
+ __compression_level) \
+ (weechat_plugin->file_compress)(__from, __to, __compressor, \
+ __compression_level)
/* util */
#define weechat_util_timeval_cmp(__time1, __time2) \