summary refs log tree commit diff stats
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/checksum/checksum.c269
-rw-r--r--plugins/checksum/meson.build1
-rw-r--r--plugins/exec/meson.build3
-rw-r--r--plugins/fishlim/fish.c61
-rw-r--r--plugins/fishlim/fish.h2
-rw-r--r--plugins/fishlim/fishlim.vcxproj4
-rw-r--r--plugins/fishlim/meson.build1
-rw-r--r--plugins/fishlim/plugin_hexchat.c6
-rw-r--r--plugins/fishlim/tests/meson.build11
-rw-r--r--plugins/fishlim/tests/mock-keystore.c (renamed from plugins/fishlim/tests/fake/keystore.c)16
-rw-r--r--plugins/fishlim/tests/old_version/fish.c155
-rw-r--r--plugins/fishlim/tests/old_version/fish.h37
-rw-r--r--plugins/fishlim/tests/old_version/meson.build4
-rw-r--r--plugins/fishlim/tests/tests.c180
-rw-r--r--plugins/fishlim/utils.c2
-rw-r--r--plugins/lua/lua.c8
-rw-r--r--plugins/perl/meson.build1
-rw-r--r--plugins/python/meson.build1
-rw-r--r--plugins/python/python.py20
-rw-r--r--plugins/python/python2.vcxproj65
-rw-r--r--plugins/python/python2.vcxproj.filters23
-rw-r--r--plugins/sysinfo/meson.build1
-rw-r--r--plugins/upd/meson.build1
-rw-r--r--plugins/upd/upd.c2
-rw-r--r--plugins/winamp/meson.build1
25 files changed, 305 insertions, 570 deletions
diff --git a/plugins/checksum/checksum.c b/plugins/checksum/checksum.c
index 6aa64b64..4db14c93 100644
--- a/plugins/checksum/checksum.c
+++ b/plugins/checksum/checksum.c
@@ -22,216 +22,162 @@
 
 #include "config.h"
 
-#include <stdlib.h>
-#include <glib.h>
-#include <glib/gstdio.h>
 #include <gio/gio.h>
 
 #include "hexchat-plugin.h"
 
-#define BUFSIZE 32768
-#define DEFAULT_LIMIT 256									/* default size is 256 MiB */
-#define SHA256_DIGEST_LENGTH 32
-#define SHA256_BUFFER_LENGTH 65
-
 static hexchat_plugin *ph;									/* plugin handle */
 static char name[] = "Checksum";
 static char desc[] = "Calculate checksum for DCC file transfers";
-static char version[] = "3.1";
-
-static void
-set_limit (char *size)
-{
-	int limit = atoi (size);
-
-	if (limit > 0 && limit < INT_MAX)
-	{
-		if (hexchat_pluginpref_set_int (ph, "limit", limit))
-			hexchat_printf (ph, "Checksum: File size limit has successfully been set to: %d MiB\n", limit);
-		else
-			hexchat_printf (ph, "Checksum: File access error while saving!\n");
-	}
-	else
-	{
-		hexchat_printf (ph, "Checksum: Invalid input!\n");
-	}
-}
-
-static int
-get_limit (void)
-{
-	int size = hexchat_pluginpref_get_int (ph, "limit");
-
-	if (size <= 0 || size >= INT_MAX)
-		return DEFAULT_LIMIT;
-	else
-		return size;
-}
-
-static gboolean
-check_limit (GFile *file)
-{
-	GFileInfo *file_info;
-	goffset file_size;
-
-	file_info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SIZE, G_FILE_QUERY_INFO_NONE,
-									NULL, NULL);
-
-	if (!file_info)
-		return FALSE;
+static char version[] = "4.0";
 
-	file_size = g_file_info_get_size (file_info);
-	g_object_unref (file_info);
 
-	if (file_size > get_limit () * 1048576ll)
-		return FALSE;
+typedef struct {
+	gboolean send_message;
+	char *servername;
+	char *channel;
+} ChecksumCallbackInfo;
 
-	return TRUE;
-}
 
-static gboolean
-sha256_from_stream (GFileInputStream *file_stream, char out_buf[])
+static void
+print_sha256_result (ChecksumCallbackInfo *info, const char *checksum, const char *filename, GError *error)
 {
-	GChecksum *checksum;
-	gssize bytes_read;
-	guint8 digest[SHA256_DIGEST_LENGTH];
-	gsize digest_len = sizeof(digest);
-	guchar buffer[BUFSIZE];
-	gsize i;
-
-	checksum = g_checksum_new (G_CHECKSUM_SHA256);
-
-	while ((bytes_read = g_input_stream_read (G_INPUT_STREAM (file_stream), buffer, sizeof (buffer), NULL, NULL)))
-	{
-		if (bytes_read == -1)
-		{
-			g_checksum_free (checksum);
-			return FALSE;
+	// So then we get the next best available channel, since we always want to print at least somewhere, it's fine
+	hexchat_context *ctx = hexchat_find_context(ph, info->servername, info->channel);
+	if (!ctx) {
+		// before we print a private message to the wrong channel, we exit early
+		if (info->send_message) {
+			return;
 		}
 
-		g_checksum_update (checksum, buffer, bytes_read);
+		// if the context isn't found the first time, we search in the server
+		ctx = hexchat_find_context(ph, info->servername, NULL);
+		if (!ctx) {
+			// The second time we exit early, since printing in another server isn't desireable
+			return;
+		}
 	}
 
-	g_checksum_get_digest (checksum, digest, &digest_len);
-	g_checksum_free (checksum);
+	hexchat_set_context(ph, ctx);
 
-	for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
-	{
-		/* out_buf will be exactly SHA256_BUFFER_LENGTH including null */
-		g_sprintf (out_buf + (i * 2), "%02x", digest[i]);
+	if (error) {
+		hexchat_printf (ph, "Failed to create checksum for %s: %s\n", filename, error->message);
+	} else if (info->send_message) {
+		hexchat_commandf (ph, "quote PRIVMSG %s :SHA-256 checksum for %s (remote): %s", hexchat_get_info (ph, "channel"), filename, checksum);
+	} else {
+		hexchat_printf (ph, "SHA-256 checksum for %s (local): %s\n", filename, checksum);
 	}
+}
 
-	return TRUE;
+static void
+file_sha256_complete (GFile *file, GAsyncResult *result, gpointer user_data)
+{	
+	ChecksumCallbackInfo * callback_info = user_data;
+	GError *error = NULL;
+	char *sha256 = NULL;
+	const char *filename = g_task_get_task_data (G_TASK (result));
+
+	sha256 = g_task_propagate_pointer (G_TASK (result), &error);
+	print_sha256_result (callback_info, sha256, filename, error);
+
+	g_free(callback_info->servername);
+	g_free(callback_info->channel);
+	g_free(callback_info);
+	g_free (sha256);
+	g_clear_error (&error);
 }
 
-static gboolean
-sha256_from_file (char *filename, char out_buf[])
+static void
+thread_sha256_file (GTask *task, GFile *file, gpointer task_data, GCancellable *cancellable)
 {
-	GFileInputStream *file_stream;
-	char *filename_fs;
-	GFile *file;
-
-	filename_fs = g_filename_from_utf8 (filename, -1, NULL, NULL, NULL);
-	if (!filename_fs)
-	{
-		hexchat_printf (ph, "Checksum: Invalid filename (%s)\n", filename);
-		return FALSE;
-	}
-
-	file = g_file_new_for_path (filename_fs);
-	g_free (filename_fs);
-	if (!file)
-	{
-		hexchat_printf (ph, "Checksum: Failed to open %s\n", filename);
-		return FALSE;
+	GChecksum *checksum;
+	GFileInputStream *istream;
+	guint8 buffer[32768];
+	GError *error = NULL;
+	gssize ret;
+
+	istream = g_file_read (file, cancellable, &error);
+	if (error) {
+		g_task_return_error (task, error);
+		return;
 	}
 
-	if (!check_limit (file))
-	{
-		hexchat_printf (ph, "Checksum: %s is larger than size limit. You can increase it with /CHECKSUM SET.\n", filename);
-		g_object_unref (file);
-		return FALSE;
-	}
+	checksum = g_checksum_new (G_CHECKSUM_SHA256);
 
-	file_stream = g_file_read (file, NULL, NULL);
-	if (!file_stream)
-	{
-		hexchat_printf (ph, "Checksum: Failed to read file %s\n", filename);
-		g_object_unref (file);
-		return FALSE;
-	}
+	while ((ret = g_input_stream_read (G_INPUT_STREAM (istream), buffer, sizeof(buffer), cancellable, &error)) > 0)
+		g_checksum_update (checksum, buffer, ret);
 
-	if (!sha256_from_stream (file_stream, out_buf))
-	{
-		hexchat_printf (ph, "Checksum: Failed to generate checksum for %s\n", filename);
-		g_object_unref (file_stream);
-		g_object_unref (file);
-		return FALSE;
+	if (error) {
+		g_checksum_free (checksum);
+		g_task_return_error (task, error);
+		return;
 	}
 
-	g_object_unref (file_stream);
-	g_object_unref (file);
-	return TRUE;
+	g_task_return_pointer (task, g_strdup (g_checksum_get_string (checksum)), g_free);
+	g_checksum_free (checksum);
 }
 
 static int
 dccrecv_cb (char *word[], void *userdata)
 {
+	GTask *task;
+	char *filename_fs;
+	GFile *file;
 	const char *dcc_completed_dir;
-	char *filename, checksum[SHA256_BUFFER_LENGTH];
-
-	/* Print in the privmsg tab of the sender */
-	hexchat_set_context (ph, hexchat_find_context (ph, NULL, word[3]));
+	char *filename;
 
 	if (hexchat_get_prefs (ph, "dcc_completed_dir", &dcc_completed_dir, NULL) == 1 && dcc_completed_dir[0] != '\0')
 		filename = g_build_filename (dcc_completed_dir, word[1], NULL);
 	else
 		filename = g_strdup (word[2]);
 
-	if (sha256_from_file (filename, checksum))
-	{
-		hexchat_printf (ph, "SHA-256 checksum for %s (local): %s\n", word[1], checksum);
+	filename_fs = g_filename_from_utf8 (filename, -1, NULL, NULL, NULL);
+	if (!filename_fs) {
+		hexchat_printf (ph, "Checksum: Invalid filename (%s)\n", filename);
+		g_free (filename);
+		return HEXCHAT_EAT_NONE;
 	}
 
-	g_free (filename);
-	return HEXCHAT_EAT_NONE;
-}
+	ChecksumCallbackInfo *callback_data = g_new (ChecksumCallbackInfo, 1);
+	callback_data->servername = g_strdup(hexchat_get_info(ph, "server"));
+	callback_data->channel = g_strdup(hexchat_get_info(ph, "channel"));
+	callback_data->send_message = FALSE;
 
-static int
-dccoffer_cb (char *word[], void *userdata)
-{
-	char checksum[SHA256_BUFFER_LENGTH];
 
-	/* Print in the privmsg tab of the receiver */
-	hexchat_set_context (ph, hexchat_find_context (ph, NULL, word[3]));
+	file = g_file_new_for_path (filename_fs);
+	task = g_task_new (file, NULL, (GAsyncReadyCallback) file_sha256_complete, (gpointer)callback_data);
+	g_task_set_task_data (task, filename, g_free);
+	g_task_run_in_thread (task, (GTaskThreadFunc) thread_sha256_file);
 
-	if (sha256_from_file (word[3], checksum))
-	{
-		hexchat_commandf (ph, "quote PRIVMSG %s :SHA-256 checksum for %s (remote): %s", word[2], word[1], checksum);
-	}
+	g_free (filename_fs);
+	g_object_unref (file);
+	g_object_unref (task);
 
 	return HEXCHAT_EAT_NONE;
 }
 
 static int
-checksum (char *word[], char *word_eol[], void *userdata)
+dccoffer_cb (char *word[], void *userdata)
 {
-	if (!g_ascii_strcasecmp ("GET", word[2]))
-	{
-		hexchat_printf (ph, "File size limit for checksums: %d MiB", get_limit ());
-	}
-	else if (!g_ascii_strcasecmp ("SET", word[2]))
-	{
-		set_limit (word[3]);
-	}
-	else
-	{
-		hexchat_printf (ph, "Usage: /CHECKSUM GET|SET\n");
-		hexchat_printf (ph, "  GET - print the maximum file size (in MiB) to be hashed\n");
-		hexchat_printf (ph, "  SET <filesize> - set the maximum file size (in MiB) to be hashed\n");
-	}
+	GFile *file;
+	GTask *task;
+	char *filename;
+
+	ChecksumCallbackInfo *callback_data = g_new (ChecksumCallbackInfo, 1);
+	callback_data->servername = g_strdup(hexchat_get_info(ph, "server"));
+	callback_data->channel = g_strdup(hexchat_get_info(ph, "channel"));
+	callback_data->send_message = TRUE;
+
+	filename = g_strdup (word[3]);
+	file = g_file_new_for_path (filename);
+	task = g_task_new (file, NULL, (GAsyncReadyCallback) file_sha256_complete, (gpointer)callback_data);
+	g_task_set_task_data (task, filename, g_free);
+	g_task_run_in_thread (task, (GTaskThreadFunc) thread_sha256_file);
+
+	g_object_unref (file);
+	g_object_unref (task);
 
-	return HEXCHAT_EAT_ALL;
+	return HEXCHAT_EAT_NONE;
 }
 
 int
@@ -243,13 +189,6 @@ hexchat_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name, char **p
 	*plugin_desc = desc;
 	*plugin_version = version;
 
-	/* this is required for the very first run */
-	if (hexchat_pluginpref_get_int (ph, "limit") == -1)
-	{
-		hexchat_pluginpref_set_int (ph, "limit", DEFAULT_LIMIT);
-	}
-
-	hexchat_hook_command (ph, "CHECKSUM", HEXCHAT_PRI_NORM, checksum, "Usage: /CHECKSUM GET|SET", NULL);
 	hexchat_hook_print (ph, "DCC RECV Complete", HEXCHAT_PRI_NORM, dccrecv_cb, NULL);
 	hexchat_hook_print (ph, "DCC Offer", HEXCHAT_PRI_NORM, dccoffer_cb, NULL);
 
diff --git a/plugins/checksum/meson.build b/plugins/checksum/meson.build
index 25835457..e3008f75 100644
--- a/plugins/checksum/meson.build
+++ b/plugins/checksum/meson.build
@@ -3,4 +3,5 @@ shared_module('checksum', 'checksum.c',
   install: true,
   install_dir: plugindir,
   name_prefix: '',
+  vs_module_defs: 'checksum.def',
 )
diff --git a/plugins/exec/meson.build b/plugins/exec/meson.build
index 3f9e8a32..782814da 100644
--- a/plugins/exec/meson.build
+++ b/plugins/exec/meson.build
@@ -1,5 +1,6 @@
 shared_module('exec', 'exec.c',
   dependencies: hexchat_plugin_dep,
   install: true,
-  install_dir: plugindir
+  install_dir: plugindir,
+  vs_module_defs: 'exec.def',
 )
diff --git a/plugins/fishlim/fish.c b/plugins/fishlim/fish.c
index c2c2b9da..0b24ed48 100644
--- a/plugins/fishlim/fish.c
+++ b/plugins/fishlim/fish.c
@@ -87,6 +87,54 @@ static const signed char fish_unbase64[256] = {
     dest |= (uint8_t)*((source)++); \
 } while (0);
 
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+#include <openssl/provider.h>
+static OSSL_PROVIDER *legacy_provider;
+static OSSL_PROVIDER *default_provider;
+static OSSL_LIB_CTX *ossl_ctx;
+#endif
+
+int fish_init(void)
+{
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+    ossl_ctx = OSSL_LIB_CTX_new();
+    if (!ossl_ctx)
+        return 0;
+
+    legacy_provider = OSSL_PROVIDER_load(ossl_ctx, "legacy");
+    if (!legacy_provider) {
+        fish_deinit();
+        return 0;
+    }
+
+    default_provider = OSSL_PROVIDER_load(ossl_ctx, "default");
+    if (!default_provider) {
+        fish_deinit();
+        return 0;
+    }
+#endif
+    return 1;
+}
+
+void fish_deinit(void)
+{
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+    if (legacy_provider) {
+        OSSL_PROVIDER_unload(legacy_provider);
+        legacy_provider = NULL;
+    }
+
+    if (default_provider) {
+        OSSL_PROVIDER_unload(default_provider);
+        default_provider = NULL;
+    }
+
+    if (ossl_ctx) {
+        OSSL_LIB_CTX_free(ossl_ctx);
+        ossl_ctx = NULL;
+    }
+#endif
+}
 
 /**
  * Encode ECB FiSH Base64
@@ -97,7 +145,8 @@ static const signed char fish_unbase64[256] = {
  */
 char *fish_base64_encode(const char *message, size_t message_len) {
     BF_LONG left = 0, right = 0;
-    int i, j;
+    int i;
+    size_t j;
     char *encoded = NULL;
     char *end = NULL;
     char *msg = NULL;
@@ -228,9 +277,19 @@ char *fish_cipher(const char *plaintext, size_t plaintext_len, const char *key,
             plaintext_len -= 8;
         }
 
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+        cipher = EVP_CIPHER_fetch(ossl_ctx, "BF-CBC", NULL);
+#else
         cipher = (EVP_CIPHER *) EVP_bf_cbc();
+#endif
+
     } else if (mode == EVP_CIPH_ECB_MODE) {
+
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+        cipher = EVP_CIPHER_fetch(ossl_ctx, "BF-ECB", NULL);
+#else
         cipher = (EVP_CIPHER *) EVP_bf_ecb();
+#endif
     }
 
     /* Zero Padding */
diff --git a/plugins/fishlim/fish.h b/plugins/fishlim/fish.h
index 6a2e911c..75829061 100644
--- a/plugins/fishlim/fish.h
+++ b/plugins/fishlim/fish.h
@@ -35,6 +35,8 @@ enum fish_mode {
   FISH_CBC_MODE = 0x2
 };
 
+int fish_init(void);
+void fish_deinit(void);
 char *fish_base64_encode(const char *message, size_t message_len);
 char *fish_base64_decode(const char *message, size_t *final_len);
 char *fish_encrypt(const char *key, size_t keylen, const char *message, size_t message_len, enum fish_mode mode);
diff --git a/plugins/fishlim/fishlim.vcxproj b/plugins/fishlim/fishlim.vcxproj
index 579c2436..3661e1e6 100644
--- a/plugins/fishlim/fishlim.vcxproj
+++ b/plugins/fishlim/fishlim.vcxproj
@@ -29,7 +29,7 @@
   </PropertyGroup>

   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

     <ClCompile>

-      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;FISHLIM_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;FISHLIM_EXPORTS;HAVE_DH_SET0_PQG;HAVE_DH_GET0_KEY;HAVE_DH_SET0_KEY;%(PreprocessorDefinitions)</PreprocessorDefinitions>

       <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

@@ -40,7 +40,7 @@
   </ItemDefinitionGroup>

   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

     <ClCompile>

-      <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;FISHLIM_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;FISHLIM_EXPORTS;HAVE_DH_SET0_PQG;HAVE_DH_GET0_KEY;HAVE_DH_SET0_KEY;%(PreprocessorDefinitions)</PreprocessorDefinitions>

       <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

diff --git a/plugins/fishlim/meson.build b/plugins/fishlim/meson.build
index 65ccc9ea..232c9a33 100644
--- a/plugins/fishlim/meson.build
+++ b/plugins/fishlim/meson.build
@@ -19,4 +19,5 @@ shared_module('fishlim', fishlim_sources,
   install: true,
   install_dir: plugindir,
   name_prefix: '',
+  vs_module_defs: 'fishlim.def',
 )
diff --git a/plugins/fishlim/plugin_hexchat.c b/plugins/fishlim/plugin_hexchat.c
index 83286e28..a8b127f2 100644
--- a/plugins/fishlim/plugin_hexchat.c
+++ b/plugins/fishlim/plugin_hexchat.c
@@ -418,8 +418,6 @@ static int handle_keyx_notice(char *word[], char *word_eol[], void *userdata) {
         g_assert(hexchat_set_context(ph, query_ctx) == 1);
 
     dh_message++; /* : prefix */
-    if (*dh_message == '+' || *dh_message == '-')
-        dh_message++; /* identify-msg */
 
     if (g_strcmp0 (word[6], "CBC") == 0)
         mode = FISH_CBC_MODE;
@@ -817,6 +815,9 @@ int hexchat_plugin_init(hexchat_plugin *plugin_handle,
     hexchat_hook_server_attrs(ph, "TOPIC", HEXCHAT_PRI_NORM, handle_incoming, NULL);
     hexchat_hook_server_attrs(ph, "332", HEXCHAT_PRI_NORM, handle_incoming, NULL);
 
+    if (!fish_init())
+        return 0;
+
     if (!dh1080_init())
         return 0;
 
@@ -830,6 +831,7 @@ int hexchat_plugin_init(hexchat_plugin *plugin_handle,
 int hexchat_plugin_deinit(void) {
     g_clear_pointer(&pending_exchanges, g_hash_table_destroy);
     dh1080_deinit();
+    fish_deinit();
 
     hexchat_printf(ph, "%s plugin unloaded\n", plugin_name);
     return 1;
diff --git a/plugins/fishlim/tests/meson.build b/plugins/fishlim/tests/meson.build
index 3b75018e..1a0394a3 100644
--- a/plugins/fishlim/tests/meson.build
+++ b/plugins/fishlim/tests/meson.build
@@ -1,17 +1,16 @@
-subdir('old_version')
-
 fishlim_test_sources = [
   'tests.c',
-  'fake/keystore.c',
+  'mock-keystore.c',
   '../fish.c',
   '../utils.c',
 ]
 
 fishlim_tests = executable('fishlim_tests', fishlim_test_sources,
-  dependencies: [libgio_dep, libssl_dep],
-  link_with : fishlim_old_lib
+  dependencies: [libgio_dep, libssl_dep, hexchat_plugin_dep],
+  include_directories: include_directories('..'),
 )
 
 test('Fishlim Tests', fishlim_tests,
-  timeout: 90
+  protocol: 'tap',
+  timeout: 600,
 )
diff --git a/plugins/fishlim/tests/fake/keystore.c b/plugins/fishlim/tests/mock-keystore.c
index 854f38dc..57a98847 100644
--- a/plugins/fishlim/tests/fake/keystore.c
+++ b/plugins/fishlim/tests/mock-keystore.c
@@ -1,5 +1,4 @@
 /*
-
   Copyright (c) 2010 Samuel Lidén Borell <samuel@kodafritt.se>
 
   Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -22,26 +21,31 @@
 
 */
 
-#include "../../fish.h"
-
+#include "fish.h"
 
 /**
  * Extracts a key from the key store file.
  */
-char *keystore_get_key(const char *nick, enum fish_mode *mode) {
+char *
+keystore_get_key(const char *nick, enum fish_mode *mode)
+{
     return NULL;
 }
 
 /**
  * Sets a key in the key store file.
  */
-gboolean keystore_store_key(const char *nick, const char *key, enum fish_mode mode) {
+gboolean
+keystore_store_key(const char *nick, const char *key, enum fish_mode mode)
+{
     return TRUE;
 }
 
 /**
  * Deletes a nick from the key store.
  */
-gboolean keystore_delete_nick(const char *nick) {
+gboolean
+keystore_delete_nick(const char *nick)
+{
     return TRUE;
 }
diff --git a/plugins/fishlim/tests/old_version/fish.c b/plugins/fishlim/tests/old_version/fish.c
deleted file mode 100644
index 99601398..00000000
--- a/plugins/fishlim/tests/old_version/fish.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
-
-  Copyright (c) 2010 Samuel Lidén Borell <samuel@kodafritt.se>
-
-  Permission is hereby granted, free of charge, to any person obtaining a copy
-  of this software and associated documentation files (the "Software"), to deal
-  in the Software without restriction, including without limitation the rights
-  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-  copies of the Software, and to permit persons to whom the Software is
-  furnished to do so, subject to the following conditions:
-
-  The above copyright notice and this permission notice shall be included in
-  all copies or substantial portions of the Software.
-
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-  THE SOFTWARE.
-
-*/
-
-#ifdef __APPLE__
-#define __AVAILABILITYMACROS__
-#define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include <openssl/blowfish.h>
-
-#include "fish.h"
-
-#define IB 64
-static const char fish_base64[64] = "./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
-static const signed char fish_unbase64[256] = {
-    IB,IB,IB,IB,IB,IB,IB,IB,  IB,IB,IB,IB,IB,IB,IB,IB,
-    IB,IB,IB,IB,IB,IB,IB,IB,  IB,IB,IB,IB,IB,IB,IB,IB,
-/*      !  "  #  $  %  &  '  (    )  *  +  ,  -  .  / */
-    IB,IB,IB,IB,IB,IB,IB,IB,  IB,IB,IB,IB,IB,IB, 0, 1,
-/*   0  1  2  3  4  5  6  7    8  9  :  ;  <  =  >  ? */
-     2, 3, 4, 5, 6, 7, 8, 9,  10,11,IB,IB,IB,IB,IB,IB,
-/*   @  A  B  C  D  E  F  G    H  I  J  K  L  M  N  O */
-    IB,38,39,40,41,42,43,44,  45,46,47,48,49,50,51,52,
-/*   P  Q  R  S  T  U  V  W    X  Y  Z  [  \  ]  ^  _*/
-    53,54,55,56,57,58,59,60,  61,62,63,IB,IB,IB,IB,IB,
-/*   `  a  b  c  d  e  f  g    h  i  j  k  l  m  n  o */
-    IB,12,13,14,15,16,17,18,  19,20,21,22,23,24,25,26,
-/*   p  q  r  s  t  u  v  w    x  y  z  {  |  }  ~  <del> */
-    27,28,29,30,31,32,33,34,  35,36,37,IB,IB,IB,IB,IB,
-};
-
-#define GET_BYTES(dest, source) do { \
-    *((dest)++) = ((source) >> 24) & 0xFF; \
-    *((dest)++) = ((source) >> 16) & 0xFF; \
-    *((dest)++) = ((source) >> 8) & 0xFF; \
-    *((dest)++) = (source) & 0xFF; \
-} while (0);
-
-
-char *__old_fish_encrypt(const char *key, size_t keylen, const char *message) {
-    BF_KEY bfkey;
-    size_t messagelen;
-    size_t i;
-    int j;
-    char *encrypted;
-    char *end;
-    unsigned char bit;
-    unsigned char word;
-    unsigned char d;
-    BF_set_key(&bfkey, keylen, (const unsigned char*)key);
-    
-    messagelen = strlen(message);
-    if (messagelen == 0) return NULL;
-    encrypted = g_malloc(((messagelen - 1) / 8) * 12 + 12 + 1); /* each 8-byte block becomes 12 bytes */
-    end = encrypted;
-     
-    while (*message) {
-        /* Read 8 bytes (a Blowfish block) */
-        BF_LONG binary[2] = { 0, 0 };
-        unsigned char c;
-        for (i = 0; i < 8; i++) {
-            c = message[i];
-            binary[i >> 2] |= c << 8*(3 - (i&3));
-            if (c == '\0') break;
-        }
-        message += 8;
-        
-        /* Encrypt block */
-        BF_encrypt(binary, &bfkey);
-        
-        /* Emit FiSH-BASE64 */
-        bit = 0;
-        word = 1;
-        for (j = 0; j < 12; j++) {
-            d = fish_base64[(binary[word] >> bit) & 63];
-            *(end++) = d;
-            bit += 6;
-            if (j == 5) {
-                bit = 0;
-                word = 0;
-            }
-        }
-        
-        /* Stop if a null terminator was found */
-        if (c == '\0') break;
-    }
-    *end = '\0';
-    return encrypted;
-}
-
-
-char *__old_fish_decrypt(const char *key, size_t keylen, const char *data) {
-    BF_KEY bfkey;
-    size_t i;
-    char *decrypted;
-    char *end;
-    unsigned char bit;
-    unsigned char word;
-    unsigned char d;
-    BF_set_key(&bfkey, keylen, (const unsigned char*)key);
-    
-    decrypted = g_malloc(strlen(data) + 1);
-    end = decrypted;
-    
-    while (*data) {
-        /* Convert from FiSH-BASE64 */
-        BF_LONG binary[2] = { 0, 0 };
-        bit = 0;
-        word = 1;
-        for (i = 0; i < 12; i++) {
-            d = fish_unbase64[(const unsigned char)*(data++)];
-            if (d == IB) goto decrypt_end;
-            binary[word] |= (unsigned long)d << bit;
-            bit += 6;
-            if (i == 5) {
-                bit = 0;
-                word = 0;
-            }
-        }
-        
-        /* Decrypt block */
-        BF_decrypt(binary, &bfkey);
-        
-        /* Copy to buffer */
-        GET_BYTES(end, binary[0]);
-        GET_BYTES(end, binary[1]);
-    }
-    
-  decrypt_end:
-    *end = '\0';
-    return decrypted;
-}
\ No newline at end of file
diff --git a/plugins/fishlim/tests/old_version/fish.h b/plugins/fishlim/tests/old_version/fish.h
deleted file mode 100644
index 7037782b..00000000
--- a/plugins/fishlim/tests/old_version/fish.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
-
-  Copyright (c) 2010 Samuel Lidén Borell <samuel@kodafritt.se>
-
-  Permission is hereby granted, free of charge, to any person obtaining a copy
-  of this software and associated documentation files (the "Software"), to deal
-  in the Software without restriction, including without limitation the rights
-  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-  copies of the Software, and to permit persons to whom the Software is
-  furnished to do so, subject to the following conditions:
-
-  The above copyright notice and this permission notice shall be included in
-  all copies or substantial portions of the Software.
-
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-  THE SOFTWARE.
-
-*/
-
-#ifndef FISH_OLD_H
-#define FISH_OLD_H
-
-#include <stddef.h>
-
-#include <glib.h>
-
-char *__old_fish_encrypt(const char *key, size_t keylen, const char *message);
-char *__old_fish_decrypt(const char *key, size_t keylen, const char *data);
-
-#endif
-
-
diff --git a/plugins/fishlim/tests/old_version/meson.build b/plugins/fishlim/tests/old_version/meson.build
deleted file mode 100644
index 54647d71..00000000
--- a/plugins/fishlim/tests/old_version/meson.build
+++ /dev/null
@@ -1,4 +0,0 @@
-fishlim_old_lib = shared_library('fishlim_old_lib',
-  ['fish.c'],
-  dependencies: [libgio_dep, libssl_dep],
-)
diff --git a/plugins/fishlim/tests/tests.c b/plugins/fishlim/tests/tests.c
index bb841c5e..553816d3 100644
--- a/plugins/fishlim/tests/tests.c
+++ b/plugins/fishlim/tests/tests.c
@@ -1,5 +1,4 @@
 /*
-
   Copyright (c) 2020 <bakasura@protonmail.ch>
 
   Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -22,24 +21,22 @@
 
 */
 
-#ifndef PLUGIN_HEXCHAT_FISHLIM_TEST_H
-#define PLUGIN_HEXCHAT_FISHLIM_TEST_H
-
-// Libs
+#include <string.h>
 #include <glib.h>
-// Project Libs
-#include "../fish.h"
-#include "../utils.h"
-#include "old_version/fish.h"
+
+#include "fish.h"
+#include "utils.h"
 
 /**
  * Auxiliary function: Generate a random string
  * @param out Preallocated string to fill
  * @param len Size of bytes to fill
  */
-void random_string(char *out, size_t len) {
+static void
+random_string(char *out, size_t len)
+{
     GRand *rand = NULL;
-    int i = 0;
+    size_t i = 0;
 
     rand = g_rand_new();
     for (i = 0; i < len; ++i) {
@@ -51,13 +48,14 @@ void random_string(char *out, size_t len) {
     g_rand_free(rand);
 }
 
-
 /**
- * Check encrypt and decrypt in ECB mode and compare with old implementation
+ * Check encrypt and decrypt in ECB mode
  */
-void __ecb(void) {
-    char *bo64 = NULL, *b64 = NULL;
-    char *deo = NULL, *de = NULL;
+static void
+test_ecb(void)
+{
+    char *b64 = NULL;
+    char *de = NULL;
     int key_len, message_len = 0;
     char key[57];
     char message[1000];
@@ -71,36 +69,20 @@ void __ecb(void) {
             random_string(message, message_len);
 
             /* Encrypt */
-            bo64 = __old_fish_encrypt(key, key_len, message);
-            g_assert_nonnull(bo64);
             b64 = fish_encrypt(key, key_len, message, message_len, FISH_ECB_MODE);
             g_assert_nonnull(b64);
-            g_assert_cmpuint(g_strcmp0(b64, bo64), == , 0);
 
             /* Decrypt */
             /* Linear */
-            deo = __old_fish_decrypt(key, key_len, bo64);
             de = fish_decrypt_str(key, key_len, b64, FISH_ECB_MODE);
-            g_assert_nonnull(deo);
-            g_assert_nonnull(de);
-            g_assert_cmpuint(g_strcmp0(de, message), == , 0);
-            g_assert_cmpuint(g_strcmp0(deo, message), == , 0);
-            g_assert_cmpuint(g_strcmp0(de, deo), == , 0);
-            g_free(deo);
+			g_assert_cmpstr (de, ==, message);
             g_free(de);
+	
             /* Mixed */
-            deo = __old_fish_decrypt(key, key_len, b64);
-            de = fish_decrypt_str(key, key_len, bo64, FISH_ECB_MODE);
-            g_assert_nonnull(deo);
-            g_assert_nonnull(de);
-            g_assert_cmpuint(g_strcmp0(de, message), == , 0);
-            g_assert_cmpuint(g_strcmp0(deo, message), == , 0);
-            g_assert_cmpuint(g_strcmp0(de, deo), == , 0);
-            g_free(deo);
+            de = fish_decrypt_str(key, key_len, b64, FISH_ECB_MODE);
+			g_assert_cmpstr (de, ==, message);
             g_free(de);
 
-            /* Free */
-            g_free(bo64);
             g_free(b64);
         }
     }
@@ -109,7 +91,9 @@ void __ecb(void) {
 /**
  * Check encrypt and decrypt in CBC mode
  */
-void __cbc(void) {
+static void
+test_cbc(void)
+{
     char *b64 = NULL;
     char *de = NULL;
     int key_len, message_len = 0;
@@ -131,11 +115,9 @@ void __cbc(void) {
             /* Decrypt */
             /* Linear */
             de = fish_decrypt_str(key, key_len, b64, FISH_CBC_MODE);
-            g_assert_nonnull(de);
-            g_assert_cmpuint(g_strcmp0(de, message), == , 0);
+            g_assert_cmpstr (de, ==, message);
             g_free(de);
 
-            /* Free */
             g_free(b64);
         }
     }
@@ -144,48 +126,49 @@ void __cbc(void) {
 /**
  * Check the calculation of final length from an encoded string in Base64
  */
-void __base64_len(void) {
+static void
+test_base64_len (void)
+{
     char *b64 = NULL;
-    int i, message_len = 0;
     char message[1000];
+    int message_end = sizeof (message) - 1;
 
-    for (i = 0; i < 10; ++i) {
+    random_string(message, message_end);
 
-        for (message_len = 1; message_len < 1000; ++message_len) {
-            random_string(message, message_len);
-            b64 = g_base64_encode((const unsigned char *) message, message_len);
-            g_assert_nonnull(b64);
-            g_assert_cmpuint(strlen(b64), == , base64_len(message_len));
-            g_free(b64);
-        }
+    for (; message_end >= 0; --message_end) {
+        message[message_end] = '\0'; /* Truncate instead of generating new strings */
+        b64 = g_base64_encode((const unsigned char *) message, message_end);
+        g_assert_nonnull(b64);
+        g_assert_cmpuint(strlen(b64), == , base64_len(message_end));
+        g_free(b64);
     }
 }
 
 /**
  * Check the calculation of final length from an encoded string in BlowcryptBase64
  */
-void __base64_fish_len(void) {
+static void
+test_base64_fish_len (void)
+{
     char *b64 = NULL;
-    int i, message_len = 0;
+    int message_len = 0;
     char message[1000];
 
-    for (i = 0; i < 10; ++i) {
-
-        for (message_len = 1; message_len < 1000; ++message_len) {
-            random_string(message, message_len);
-            b64 = fish_base64_encode(message, message_len);
-            g_assert_nonnull(b64);
-            g_assert_cmpuint(strlen(b64), == , base64_fish_len(message_len));
-            g_free(b64);
-        }
+    for (message_len = 1; message_len < 1000; ++message_len) {
+        random_string(message, message_len);
+        b64 = fish_base64_encode(message, message_len);
+        g_assert_nonnull(b64);
+        g_assert_cmpuint(strlen(b64), == , base64_fish_len(message_len));
+        g_free(b64);
     }
 }
 
-
 /**
  * Check the calculation of final length from an encrypted string in ECB mode
  */
-void __base64_ecb_len(void) {
+static void
+test_base64_ecb_len(void)
+{
     char *b64 = NULL;
     int key_len, message_len = 0;
     char key[57];
@@ -209,7 +192,9 @@ void __base64_ecb_len(void) {
 /**
  * Check the calculation of final length from an encrypted string in CBC mode
  */
-void __base64_cbc_len(void) {
+static void
+test_base64_cbc_len(void)
+{
     char *b64 = NULL;
     int key_len, message_len = 0;
     char key[57];
@@ -233,7 +218,9 @@ void __base64_cbc_len(void) {
 /**
  * Check the calculation of length limit for a plaintext in each encryption mode
  */
-void __max_text_command_len(void) {
+static void
+test_max_text_command_len(void)
+{
     int max_encoded_len, plaintext_len;
     enum fish_mode mode;
 
@@ -248,50 +235,51 @@ void __max_text_command_len(void) {
 /**
  * Check the calculation of length limit for a plaintext in each encryption mode
  */
-void __foreach_utf8_data_chunks(void) {
+static void
+test_foreach_utf8_data_chunks(void)
+{
     GRand *rand = NULL;
     GString *chunks = NULL;
-    int tests, max_chunks_len, chunks_len;
+    int  max_chunks_len, chunks_len;
     char ascii_message[1001];
     char *data_chunk = NULL;
 
     rand = g_rand_new();
+    max_chunks_len = g_rand_int_range(rand, 2, 301);
+    random_string(ascii_message, 1000);
 
-    for (tests = 0; tests < 1000; ++tests) {
-
-        max_chunks_len = g_rand_int_range(rand, 2, 301);
-        random_string(ascii_message, 1000);
+    data_chunk = ascii_message;
 
-        data_chunk = ascii_message;
+    chunks = g_string_new(NULL);
 
-        chunks = g_string_new(NULL);
-
-        while (foreach_utf8_data_chunks(data_chunk, max_chunks_len, &chunks_len)) {
-            g_string_append(chunks, g_strndup(data_chunk, chunks_len));
-            /* Next chunk */
-            data_chunk += chunks_len;
-        }
-        /* Check data loss */
-        g_assert_cmpstr(chunks->str, == , ascii_message);
-        g_string_free(chunks, TRUE);
+    while (foreach_utf8_data_chunks(data_chunk, max_chunks_len, &chunks_len)) {
+        g_string_append(chunks, g_strndup(data_chunk, chunks_len));
+        /* Next chunk */
+        data_chunk += chunks_len;
     }
-}
+    /* Check data loss */
+    g_assert_cmpstr(chunks->str, == , ascii_message);
 
+    g_string_free(chunks, TRUE);
+    g_rand_free (rand);
+}
 
-int main(int argc, char *argv[]) {
+int
+main(int argc, char *argv[]) {
 
     g_test_init(&argc, &argv, NULL);
 
-    g_test_add_func("/fishlim/__ecb", __ecb);
-    g_test_add_func("/fishlim/__cbc", __ecb);
-    g_test_add_func("/fishlim/__base64_len", __base64_len);
-    g_test_add_func("/fishlim/__base64_fish_len", __base64_fish_len);
-    g_test_add_func("/fishlim/__base64_ecb_len", __base64_ecb_len);
-    g_test_add_func("/fishlim/__base64_cbc_len", __base64_cbc_len);
-    g_test_add_func("/fishlim/__max_text_command_len", __max_text_command_len);
-    g_test_add_func("/fishlim/__foreach_utf8_data_chunks", __foreach_utf8_data_chunks);
-
-    return g_test_run();
+    g_test_add_func("/fishlim/ecb", test_ecb);
+    g_test_add_func("/fishlim/cbc", test_cbc);
+    g_test_add_func("/fishlim/base64_len", test_base64_len);
+    g_test_add_func("/fishlim/base64_fish_len", test_base64_fish_len);
+    g_test_add_func("/fishlim/base64_ecb_len", test_base64_ecb_len);
+    g_test_add_func("/fishlim/base64_cbc_len", test_base64_cbc_len);
+    g_test_add_func("/fishlim/max_text_command_len", test_max_text_command_len);
+    g_test_add_func("/fishlim/foreach_utf8_data_chunks", test_foreach_utf8_data_chunks);
+
+    fish_init();
+    int ret = g_test_run();
+    fish_deinit();
+    return ret;
 }
-
-#endif //PLUGIN_HEXCHAT_FISHLIM_TEST_H
\ No newline at end of file
diff --git a/plugins/fishlim/utils.c b/plugins/fishlim/utils.c
index 4052995a..17ed4c2e 100644
--- a/plugins/fishlim/utils.c
+++ b/plugins/fishlim/utils.c
@@ -22,6 +22,8 @@
 
 */
 
+#include <string.h>
+
 #include "utils.h"
 #include "fish.h"
 
diff --git a/plugins/lua/lua.c b/plugins/lua/lua.c
index d1370eaf..f8f051f4 100644
--- a/plugins/lua/lua.c
+++ b/plugins/lua/lua.c
@@ -957,16 +957,21 @@ static int api_hexchat_pluginprefs_meta_pairs(lua_State *L)
 	hexchat_plugin *h;
 
 	if(!script->name)
+
 		return luaL_error(L, "cannot use hexchat.pluginprefs before registering with hexchat.register");
 
 	dest = lua_newuserdata(L, 4096);
+
 	h = script->handle;
 	if(!hexchat_pluginpref_list(h, dest))
 		strcpy(dest, "");
 	lua_pushlightuserdata(L, dest);
 	lua_pushlightuserdata(L, dest);
 	lua_pushcclosure(L, api_hexchat_pluginprefs_meta_pairs_closure, 2);
-	return 1;
+	lua_insert(L, -2); // Return the userdata (second return value from pairs),
+						// even though it's not used by the closure (first return
+						// value from pairs), so that Lua knows not to GC it.
+	return 2;
 }
 
 static int api_attrs_meta_index(lua_State *L)
@@ -1764,4 +1769,3 @@ G_MODULE_EXPORT int hexchat_plugin_deinit(hexchat_plugin *plugin_handle)
 	g_clear_pointer(&expand_buffer, g_free);
 	return 1;
 }
-
diff --git a/plugins/perl/meson.build b/plugins/perl/meson.build
index 06ffd54b..ebcf35bb 100644
--- a/plugins/perl/meson.build
+++ b/plugins/perl/meson.build
@@ -88,4 +88,5 @@ shared_module('perl',
   install_dir: plugindir,
   install_rpath: perl_rpath,
   name_prefix: '',
+  vs_module_defs: 'perl.def',
 )
diff --git a/plugins/python/meson.build b/plugins/python/meson.build
index 5fd7ec2f..1e9b41ad 100644
--- a/plugins/python/meson.build
+++ b/plugins/python/meson.build
@@ -28,4 +28,5 @@ shared_module('python', python3_source,
   install: true,
   install_dir: plugindir,
   name_prefix: '',
+  vs_module_defs: 'python.def'
 )
diff --git a/plugins/python/python.py b/plugins/python/python.py
index 7bd327e3..9eca7d6e 100644
--- a/plugins/python/python.py
+++ b/plugins/python/python.py
@@ -64,6 +64,10 @@ class Stdout:
         else:
             self.buffer += string
 
+    def flush(self):
+        lib.hexchat_print(lib.ph, bytes(self.buffer))
+        self.buffer = bytearray()
+
     def isatty(self):
         return False
 
@@ -146,8 +150,8 @@ class Plugin:
     def loadfile(self, filename):
         try:
             self.filename = filename
-            with open(filename) as f:
-                data = f.read()
+            with open(filename, 'rb') as f:
+                data = f.read().decode('utf-8')
             compiled = compile_file(data, filename)
             exec(compiled, self.globals)
 
@@ -284,10 +288,18 @@ def _on_server_attrs_hook(word, word_eol, attrs, userdata):
 @ffi.def_extern()
 def _on_timer_hook(userdata):
     hook = ffi.from_handle(userdata)
-    if hook.callback(hook.userdata) is True:
+    if hook.callback(hook.userdata) == True:
         return 1
 
-    hook.is_unload = True  # Don't unhook
+    try:
+        # Avoid calling hexchat_unhook twice if unnecessary
+        hook.is_unload = True
+    except ReferenceError:
+        # hook is a weak reference, it might have been destroyed by the callback
+        # in which case it has already been removed from hook.plugin.hooks and
+        # we wouldn't be able to test it with h == hook anyway.
+        return 0
+
     for h in hook.plugin.hooks:
         if h == hook:
             hook.plugin.hooks.remove(h)
diff --git a/plugins/python/python2.vcxproj b/plugins/python/python2.vcxproj
deleted file mode 100644
index 42895ce4..00000000
--- a/plugins/python/python2.vcxproj
+++ /dev/null
@@ -1,65 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <PropertyGroup Label="Configuration">

-    <PlatformToolset>v142</PlatformToolset>

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-  </PropertyGroup>

-  <ItemGroup Label="ProjectConfigurations">

-    <ProjectConfiguration Include="Release|Win32">

-      <Configuration>Release</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Release|x64">

-      <Configuration>Release</Configuration>

-      <Platform>x64</Platform>

-    </ProjectConfiguration>

-  </ItemGroup>

-  <PropertyGroup Label="Globals">

-    <ProjectGuid>{19C52A0A-A790-409E-A28A-9745FF990F5C}</ProjectGuid>

-    <Keyword>Win32Proj</Keyword>

-    <RootNamespace>python2</RootNamespace>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

-  <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  <Import Project="..\..\win32\hexchat.props" />

-  <PropertyGroup>

-    <TargetName>$(Python2Output)</TargetName>

-    <OutDir>$(HexChatRel)plugins\</OutDir>

-  </PropertyGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-    <ClCompile>

-      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;PYTHON_EXPORTS;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>$(Glib);$(Python2Path)\include;..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-    </ClCompile>

-    <Link>

-      <ModuleDefinitionFile>python.def</ModuleDefinitionFile>

-      <AdditionalDependencies>"$(Python2Lib).lib";$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

-      <AdditionalLibraryDirectories>$(DepsRoot)\lib;$(Python2Path)\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-    </Link>

-    <PreBuildEvent>

-      <Command>"$(Python3Path)\python.exe" generate_plugin.py ..\..\src\common\hexchat-plugin.h python.py "$(IntDir)python.c"</Command>

-    </PreBuildEvent>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

-    <ClCompile>

-      <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;PYTHON_EXPORTS;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>$(Glib);$(Python2Path)\include;..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

-    </ClCompile>

-    <Link>

-      <ModuleDefinitionFile>python.def</ModuleDefinitionFile>

-      <AdditionalDependencies>"$(Python2Lib).lib";$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

-      <AdditionalLibraryDirectories>$(DepsRoot)\lib;$(Python2Path)\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

-    </Link>

-    <PreBuildEvent>

-      <Command>"$(Python3Path)\python.exe" generate_plugin.py ..\..\src\common\hexchat-plugin.h python.py "$(IntDir)python.c"</Command>

-    </PreBuildEvent>

-  </ItemDefinitionGroup>

-  <ItemGroup>

-    <None Include="python.def" />

-  </ItemGroup>

-  <ItemGroup>

-    <ClCompile Include="$(IntDir)python.c" />

-  </ItemGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

-</Project>

diff --git a/plugins/python/python2.vcxproj.filters b/plugins/python/python2.vcxproj.filters
deleted file mode 100644
index d56e53b6..00000000
--- a/plugins/python/python2.vcxproj.filters
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <ItemGroup>

-    <Filter Include="Source Files">

-      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>

-      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>

-    </Filter>

-    <Filter Include="Resource Files">

-      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>

-      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>

-    </Filter>

-  </ItemGroup>

-  <ItemGroup>

-    <None Include="python.def">

-      <Filter>Resource Files</Filter>

-    </None>

-  </ItemGroup>

-  <ItemGroup>

-    <ClCompile Include="python.c">

-      <Filter>Source Files</Filter>

-    </ClCompile>

-  </ItemGroup>

-</Project>
\ No newline at end of file
diff --git a/plugins/sysinfo/meson.build b/plugins/sysinfo/meson.build
index 7e2cdb6c..08f08c2c 100644
--- a/plugins/sysinfo/meson.build
+++ b/plugins/sysinfo/meson.build
@@ -57,4 +57,5 @@ shared_module('sysinfo', sysinfo_sources,
   install: true,
   install_dir: plugindir,
   name_prefix: '',
+  vs_module_defs: 'sysinfo.def',
 )
diff --git a/plugins/upd/meson.build b/plugins/upd/meson.build
index 7ab9d830..68217b31 100644
--- a/plugins/upd/meson.build
+++ b/plugins/upd/meson.build
@@ -5,4 +5,5 @@ shared_module('upd', 'upd.c',
   install: true,
   install_dir: plugindir,
   name_prefix: '',
+  vs_module_defs: 'upd.def',
 )
diff --git a/plugins/upd/upd.c b/plugins/upd/upd.c
index c9011c04..2a938596 100644
--- a/plugins/upd/upd.c
+++ b/plugins/upd/upd.c
@@ -24,7 +24,7 @@
 
 #include "hexchat-plugin.h"
 
-#define APPCAST_URL "https://dl.hexchat.net/appcast.xml"
+#define APPCAST_URL "https://hexchat.github.io/appcast.xml"
 
 static hexchat_plugin *ph;   /* plugin handle */
 static char name[] = "Update Checker";
diff --git a/plugins/winamp/meson.build b/plugins/winamp/meson.build
index b07e7071..8d298651 100644
--- a/plugins/winamp/meson.build
+++ b/plugins/winamp/meson.build
@@ -3,4 +3,5 @@ shared_module('winamp', 'winamp.c',
   install: true,
   install_dir: plugindir,
   name_prefix: '',
+  vs_module_defs: 'winamp.def',
 )