Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/Remmina/Remmina.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorToolsDevler <info@toolsdevler.net>2020-08-17 11:13:47 +0300
committerToolsDevler <info@toolsdevler.net>2020-12-31 03:03:24 +0300
commit178758c8f95410936762f43867adea348fbd1dc7 (patch)
tree03b34e3e6372104af6e13238d6c63190da7531bd
parent7930213724f5f12fcf47fb8973cffad0ad871103 (diff)
WIP: Python plugin implementation
-rw-r--r--CMakeLists.txt1
-rw-r--r--plugins/common/remmina_plugin_python.h62
-rw-r--r--src/CMakeLists.txt8
-rw-r--r--src/remmina.c7
-rw-r--r--src/remmina_plugin_manager.c63
-rw-r--r--src/remmina_plugin_manager.h9
-rw-r--r--src/remmina_plugin_native.c47
-rw-r--r--src/remmina_plugin_native.h47
-rw-r--r--src/remmina_plugin_python.c302
-rw-r--r--src/remmina_plugin_python.h45
10 files changed, 565 insertions, 26 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 839faed54..116bdc41a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -303,6 +303,7 @@ add_custom_target(uninstall "${CMAKE_COMMAND}" -P
find_required_package(GTK)
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
+
find_package(Threads REQUIRED)
if(NOT CMAKE_USE_PTHREADS_INIT)
message(FATAL_ERROR "pthreads thread library not found")
diff --git a/plugins/common/remmina_plugin_python.h b/plugins/common/remmina_plugin_python.h
new file mode 100644
index 000000000..5915adb82
--- /dev/null
+++ b/plugins/common/remmina_plugin_python.h
@@ -0,0 +1,62 @@
+#pragma once
+
+#include <Python.h>
+#include "common/remmina_plugin.h"
+
+static PyTypeObject remmina_remmina_protocol_widget = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "remmina.remmina_protocol_widget", /* tp_name */
+ sizeof(remmina_remmina_protocol_widget), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ "remmina_protocol_widget", /* tp_doc */
+};
+
+static PyTypeObject remmina_remmina_plugin = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "remmina.remmina_plugin", /* tp_name */
+ sizeof(remmina_remmina_plugin), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ "remmina_plugin", /* tp_doc */
+};
+
+static PyModuleDef remminamodule = {
+ PyModuleDef_HEAD_INIT,
+ "remmina",
+ "Example module that creates an extension type.",
+ -1,
+ NULL, NULL, NULL, NULL, NULL
+};
+
+PyMODINIT_FUNC PyInit_remmina(void);
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 297eeaa04..8149b510c 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -77,6 +77,10 @@ list(APPEND REMMINA_SRCS
"remmina_message_panel.h"
"remmina_plugin_manager.c"
"remmina_plugin_manager.h"
+ "remmina_plugin_native.c"
+ "remmina_plugin_native.h"
+ "remmina_plugin_python.c"
+ "remmina_plugin_python.h"
"remmina_ext_exec.c"
"remmina_ext_exec.h"
"remmina_pref.c"
@@ -131,6 +135,10 @@ add_executable(remmina ${REMMINA_SRCS})
include_directories(${GTK_INCLUDE_DIRS} ${gio_INCLUDE_DIRS} ${gio-unix_INCLUDE_DIRS})
target_link_libraries(remmina ${GTK_LIBRARIES})
+find_package(PythonLibs REQUIRED)
+include_directories(${PYTHON_INCLUDE_DIRS})
+target_link_libraries(remmina ${PYTHON_LIBRARIES})
+
if(WITH_MANPAGES)
install(FILES remmina.1 DESTINATION ${CMAKE_INSTALL_FULL_MANDIR}/man1)
endif()
diff --git a/src/remmina.c b/src/remmina.c
index 25563ee35..f1f28df43 100644
--- a/src/remmina.c
+++ b/src/remmina.c
@@ -49,6 +49,8 @@
#include "remmina_main.h"
#include "remmina_masterthread_exec.h"
#include "remmina_plugin_manager.h"
+#include "remmina_plugin_native.h"
+#include "remmina_plugin_python.h"
#include "remmina_pref.h"
#include "remmina_public.h"
#include "remmina_sftp_plugin.h"
@@ -354,7 +356,12 @@ int main(int argc, char *argv[])
/* Initialize some Remmina parts needed also on a local instance for correct handle-local-options */
remmina_pref_init();
remmina_file_manager_init();
+
+ remmina_plugin_manager_add_loader("so", remmina_plugin_native_load);
+ remmina_plugin_manager_add_loader("py", remmina_plugin_python_load);
+
remmina_plugin_manager_init();
+
app_id = g_application_id_is_valid(REMMINA_APP_ID) ? REMMINA_APP_ID : NULL;
diff --git a/src/remmina_plugin_manager.c b/src/remmina_plugin_manager.c
index 6bc3abade..63ab2f2db 100644
--- a/src/remmina_plugin_manager.c
+++ b/src/remmina_plugin_manager.c
@@ -68,6 +68,9 @@ static RemminaSecretPlugin *remmina_secret_plugin = NULL;
static const gchar *remmina_plugin_type_name[] =
{ N_("Protocol"), N_("Entry"), N_("File"), N_("Tool"), N_("Preference"), N_("Secret"), NULL };
+
+GPtrArray* remmina_plugin_loaders = NULL;
+
static gint remmina_plugin_manager_compare_func(RemminaPlugin **a, RemminaPlugin **b)
{
TRACE_CALL(__func__);
@@ -166,8 +169,6 @@ gboolean remmina_gtksocket_available()
return available;
}
-
-
RemminaPluginService remmina_plugin_manager_service =
{
remmina_plugin_manager_register_plugin,
@@ -248,34 +249,32 @@ RemminaPluginService remmina_plugin_manager_service =
remmina_gtksocket_available,
remmina_protocol_widget_get_profile_remote_width,
remmina_protocol_widget_get_profile_remote_height
-
};
-static void remmina_plugin_manager_load_plugin(const gchar *name)
-{
- TRACE_CALL(__func__);
- GModule *module;
- RemminaPluginEntryFunc entry;
-
- module = g_module_open(name, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
-
- if (!module) {
- g_print("Could not load plugin: %s.\n", name);
- g_print("Error: %s\n", g_module_error());
- return;
- }
+typedef struct {
+ const gchar* filetype;
+ const gchar* name;
+} RemminaPluginLoaderArgs;
- if (!g_module_symbol(module, "remmina_plugin_entry", (gpointer*)&entry)) {
- g_print("Could not locate plugin entry: %s.\n", name);
- return;
- }
+const char *get_filename_ext(const char *filename) {
+ const char *dot = strrchr(filename, '.');
+ if(!dot || dot == filename) return "";
+ return dot + 1;
+}
- if (!entry(&remmina_plugin_manager_service)) {
- g_print("Plugin entry returned false: %s.\n", name);
- return;
+static void remmina_plugin_manager_use_loader(const RemminaPluginLoader* loader, const RemminaPluginLoaderArgs* args) {
+ if (g_str_equal(loader->filetype, args->filetype)) {
+ loader->func(&remmina_plugin_manager_service, args->name);
}
+}
- /* We don’t close the module because we will need it throughout the process lifetime */
+static void remmina_plugin_manager_load_plugin(char *name)
+{
+ const char* ext = get_filename_ext(name);
+ RemminaPluginLoaderArgs args;
+ args.filetype = ext;
+ args.name = name;
+ g_ptr_array_foreach(remmina_plugin_loaders, (GFunc)remmina_plugin_manager_use_loader, &args);
}
static gint compare_secret_plugin_init_order(gconstpointer a, gconstpointer b)
@@ -292,7 +291,7 @@ static gint compare_secret_plugin_init_order(gconstpointer a, gconstpointer b)
return 0;
}
-void remmina_plugin_manager_init(void)
+void remmina_plugin_manager_init()
{
TRACE_CALL(__func__);
GDir *dir;
@@ -311,14 +310,16 @@ void remmina_plugin_manager_init(void)
return;
}
+ g_print("Load modules from %s\n", REMMINA_RUNTIME_PLUGINDIR);
dir = g_dir_open(REMMINA_RUNTIME_PLUGINDIR, 0, NULL);
+
if (dir == NULL)
return;
while ((name = g_dir_read_name(dir)) != NULL) {
if ((ptr = strrchr(name, '.')) == NULL)
continue;
ptr++;
- if (g_strcmp0(ptr, G_MODULE_SUFFIX) != 0)
+ if (g_strcmp0(ptr, G_MODULE_SUFFIX) != 0 && g_strcmp0(ptr, "py"))
continue;
fullpath = g_strdup_printf(REMMINA_RUNTIME_PLUGINDIR "/%s", name);
remmina_plugin_manager_load_plugin(fullpath);
@@ -356,6 +357,16 @@ void remmina_plugin_manager_init(void)
g_slist_free(secret_plugins);
}
+void remmina_plugin_manager_add_loader(char *filetype, RemminaPluginLoaderFunc func) {
+ if (!remmina_plugin_loaders)
+ remmina_plugin_loaders = g_ptr_array_new();
+
+ RemminaPluginLoader* loader = (RemminaPluginLoader*)malloc(sizeof(RemminaPluginLoader*));
+ loader->filetype = filetype;
+ loader->func = func;
+ g_ptr_array_add(remmina_plugin_loaders, loader);
+}
+
RemminaPlugin* remmina_plugin_manager_get_plugin(RemminaPluginType type, const gchar *name)
{
TRACE_CALL(__func__);
diff --git a/src/remmina_plugin_manager.h b/src/remmina_plugin_manager.h
index bb2b3e637..578d95d5b 100644
--- a/src/remmina_plugin_manager.h
+++ b/src/remmina_plugin_manager.h
@@ -58,4 +58,13 @@ gboolean remmina_gtksocket_available();
extern RemminaPluginService remmina_plugin_manager_service;
+typedef gboolean (*RemminaPluginLoaderFunc)(RemminaPluginService*, const gchar* name);
+
+typedef struct {
+ char* filetype;
+ RemminaPluginLoaderFunc func;
+} RemminaPluginLoader;
+
+void remmina_plugin_manager_add_loader(char *filetype, RemminaPluginLoaderFunc func);
+
G_END_DECLS
diff --git a/src/remmina_plugin_native.c b/src/remmina_plugin_native.c
new file mode 100644
index 000000000..da1145ac4
--- /dev/null
+++ b/src/remmina_plugin_native.c
@@ -0,0 +1,47 @@
+#include "config.h"
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <string.h>
+
+#include <gdk/gdkx.h>
+
+#include "remmina_public.h"
+#include "remmina_file_manager.h"
+#include "remmina_pref.h"
+#include "remmina_protocol_widget.h"
+#include "remmina_log.h"
+#include "remmina_widget_pool.h"
+#include "rcw.h"
+#include "remmina_public.h"
+#include "remmina_plugin_native.h"
+#include "remmina_masterthread_exec.h"
+#include "remmina/remmina_trace_calls.h"
+
+gboolean remmina_plugin_native_load(RemminaPluginService* service, const char* name) {
+ TRACE_CALL(__func__);
+ GModule *module;
+ RemminaPluginEntryFunc entry;
+
+ module = g_module_open(name, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
+
+ if (!module) {
+ g_print("Failed to load plugin: %s.\n", name);
+ g_print("Error: %s\n", g_module_error());
+ return FALSE;
+ }
+
+ if (!g_module_symbol(module, "remmina_plugin_entry", (gpointer*)&entry)) {
+ g_print("Failed to locate plugin entry: %s.\n", name);
+ return FALSE;
+ }
+
+ if (!entry(service)) {
+ g_print("Plugin entry returned false: %s.\n", name);
+ return FALSE;
+ }
+
+ return TRUE;
+ /* We don’t close the module because we will need it throughout the process lifetime */
+}
diff --git a/src/remmina_plugin_native.h b/src/remmina_plugin_native.h
new file mode 100644
index 000000000..cc234323a
--- /dev/null
+++ b/src/remmina_plugin_native.h
@@ -0,0 +1,47 @@
+/*
+ * Remmina - The GTK+ Remote Desktop Client
+ * Copyright (C) 2010 Vic Lee
+ * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo
+ * Copyright (C) 2016-2020 Antenore Gatta, Giovanni Panozzo
+ *
+ * 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 02110-1301, USA.
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. * If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. * If you
+ * do not wish to do so, delete this exception statement from your
+ * version. * If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ *
+ */
+
+#pragma once
+
+#include "remmina_plugin_manager.h"
+
+G_BEGIN_DECLS
+
+typedef gboolean (*RemminaPluginMain)(gchar *name);
+
+gboolean remmina_plugin_native_load(RemminaPluginService* service, const char* name);
+
+G_END_DECLS
diff --git a/src/remmina_plugin_python.c b/src/remmina_plugin_python.c
new file mode 100644
index 000000000..33ca30b9d
--- /dev/null
+++ b/src/remmina_plugin_python.c
@@ -0,0 +1,302 @@
+#include "config.h"
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <string.h>
+
+#define PY_SSIZE_T_CLEAN
+#include <Python.h>
+
+#include <gdk/gdkx.h>
+
+#include "remmina_public.h"
+#include "remmina_file_manager.h"
+#include "remmina_pref.h"
+#include "common/remmina_plugin_python.h"
+#include "remmina_log.h"
+#include "remmina_widget_pool.h"
+#include "rcw.h"
+#include "remmina_public.h"
+#include "remmina_plugin_python.h"
+#include "remmina_masterthread_exec.h"
+#include "remmina/remmina_trace_calls.h"
+
+
+PyMODINIT_FUNC PyInit_remmina(void) {
+ // TODO: Initialize remmina Python module
+}
+
+static void
+remmina_protocol_widget_dealloc(Noddy* self)
+{
+ // TODO: Free memory if necessary
+}
+
+static PyObject *
+remmina_protocol_widget_init(PyTypeObject *type, PyObject *args, PyObject *kwds) {
+ // TODO: In case python creates a new widget, implement. Otherwise raise error.
+}
+
+static PyObject *
+remmina_protocol_widget_new(PyTypeObject *self, PyObject *args, PyObject *kwds) {
+ // TODO: In case python creates a new widget, implement. Otherwise raise error.
+}
+
+static PyObject* remmina_plugin_manager_python_register_plugin() {
+ remmina_plugin_manager_python_register_plugin();
+}
+
+static PyObject* remmina_protocol_python_widget_get_width() {
+ RemminaProtocolWidget *gp;
+ remmina_protocol_widget_get_width();
+}
+static PyObject* remmina_protocol_python_widget_set_width() {
+ remmina_protocol_widget_set_width();
+}
+static PyObject* remmina_protocol_python_widget_get_height() {
+ remmina_protocol_widget_get_height();
+}
+static PyObject* remmina_protocol_python_widget_set_height() {
+ remmina_protocol_widget_set_height();
+}
+static PyObject* remmina_protocol_python_widget_get_current_scale_mode() {
+ remmina_protocol_widget_get_current_scale_mode();
+}
+static PyObject* remmina_protocol_python_widget_get_expand() {
+ remmina_protocol_widget_get_expand();
+}
+static PyObject* remmina_protocol_python_widget_set_expand() {
+ remmina_protocol_widget_set_expand();
+}
+static PyObject* remmina_protocol_python_widget_has_error() {
+ remmina_protocol_widget_has_error();
+}
+static PyObject* remmina_protocol_python_widget_set_error() {
+ remmina_protocol_widget_set_error();
+}
+static PyObject* remmina_protocol_python_widget_is_closed() {
+ remmina_protocol_widget_is_closed();
+}
+static PyObject* remmina_protocol_python_widget_get_file() {
+ remmina_protocol_widget_get_file();
+}
+static PyObject* remmina_protocol_python_widget_emit_signal() {
+ remmina_protocol_widget_emit_signal();
+}
+static PyObject* remmina_protocol_python_widget_register_hostkey() {
+ remmina_protocol_widget_register_hostkey();
+}
+static PyObject* remmina_protocol_python_widget_start_direct_tunnel() {
+ remmina_protocol_widget_start_direct_tunnel();
+}
+static PyObject* remmina_protocol_python_widget_start_reverse_tunnel() {
+ remmina_protocol_widget_start_reverse_tunnel();
+}
+static PyObject* remmina_protocol_python_widget_start_xport_tunnel() {
+ remmina_protocol_widget_start_xport_tunnel();
+}
+static PyObject* remmina_protocol_python_widget_set_display() {
+ remmina_protocol_widget_set_display();
+}
+static PyObject* remmina_protocol_python_widget_signal_connection_closed() {
+ remmina_protocol_widget_signal_connection_closed();
+}
+static PyObject* remmina_protocol_python_widget_signal_connection_opened() {
+ remmina_protocol_widget_signal_connection_opened();
+}
+static PyObject* remmina_protocol_python_widget_update_align() {
+ remmina_protocol_widget_update_align();
+}
+static PyObject* remmina_protocol_python_widget_unlock_dynres() {
+ remmina_protocol_widget_unlock_dynres();
+}
+static PyObject* remmina_protocol_python_widget_desktop_resize() {
+ remmina_protocol_widget_desktop_resize();
+}
+static PyObject* remmina_protocol_python_widget_panel_auth() {
+ remmina_protocol_widget_panel_auth();
+}
+static PyObject* remmina_protocol_python_widget_panel_new_certificate() {
+ remmina_protocol_widget_panel_new_certificate();
+}
+static PyObject* remmina_protocol_python_widget_panel_changed_certificate() {
+ remmina_protocol_widget_panel_changed_certificate();
+}
+static PyObject* remmina_protocol_python_widget_get_username() {
+ remmina_protocol_widget_get_username();
+}
+static PyObject* remmina_protocol_python_widget_get_password() {
+ remmina_protocol_widget_get_password();
+}
+static PyObject* remmina_protocol_python_widget_get_domain() {
+ remmina_protocol_widget_get_domain();
+}
+static PyObject* remmina_protocol_python_widget_get_savepassword() {
+ remmina_protocol_widget_get_savepassword();
+}
+static PyObject* remmina_protocol_python_widget_panel_authx509() {
+ remmina_protocol_widget_panel_authx509();
+}
+static PyObject* remmina_protocol_python_widget_get_cacert() {
+ remmina_protocol_widget_get_cacert();
+}
+static PyObject* remmina_protocol_python_widget_get_cacrl() {
+ remmina_protocol_widget_get_cacrl();
+}
+static PyObject* remmina_protocol_python_widget_get_clientcert() {
+ remmina_protocol_widget_get_clientcert();
+}
+static PyObject* remmina_protocol_python_widget_get_clientkey() {
+ remmina_protocol_widget_get_clientkey();
+}
+static PyObject* remmina_protocol_python_widget_save_cred() {
+ remmina_protocol_widget_save_cred();
+}
+static PyObject* remmina_protocol_python_widget_panel_show_listen() {
+ remmina_protocol_widget_panel_show_listen();
+}
+static PyObject* remmina_protocol_python_widget_panel_show_retry() {
+ remmina_protocol_widget_panel_show_retry();
+}
+static PyObject* remmina_protocol_python_widget_panel_show() {
+ remmina_protocol_widget_panel_show();
+}
+static PyObject* remmina_protocol_python_widget_panel_hide() {
+ remmina_protocol_widget_panel_hide();
+}
+static PyObject* remmina_protocol_python_widget_ssh_exec() {
+ remmina_protocol_widget_ssh_exec();
+}
+static PyObject* remmina_protocol_python_widget_chat_open() {
+ remmina_protocol_widget_chat_open();
+}
+static PyObject* remmina_protocol_python_widget_chat_close() {
+ remmina_protocol_widget_chat_close();
+}
+static PyObject* remmina_protocol_python_widget_chat_receive() {
+ remmina_protocol_widget_chat_receive();
+}
+static PyObject* remmina_protocol_python_widget_send_keys_signals() {
+ remmina_protocol_widget_send_keys_signals();
+}
+
+
+ static PyObject* remmina_file_python_get_datadir() {
+ remmina_file_get_datadir();
+ }
+
+ static PyObject* remmina_file_python_new() {
+ remmina_file_new();
+ }
+
+ static PyObject* remmina_file_python_get_filename() {
+ remmina_file_get_filename();
+ }
+
+ static PyObject* remmina_file_python_set_string() {
+ remmina_file_set_string();
+ }
+
+ static PyObject* remmina_file_python_get_string() {
+ remmina_file_get_string();
+ }
+
+ static PyObject* remmina_file_python_get_secret() {
+ remmina_file_get_secret();
+ }
+
+ static PyObject* remmina_file_python_set_int() {
+ remmina_file_set_int();
+ }
+
+ static PyObject* remmina_file_python_get_int() {
+ remmina_file_get_int();
+ }
+
+ static PyObject* remmina_file_python_unsave_passwords() {
+ remmina_file_unsave_passwords();
+ }
+
+
+ static PyObject* remmina_pref_pyton_set_value() {
+ remmina_pref_set_value();
+ }
+ static PyObject* remmina_pref_pyton_get_value() {
+ remmina_pref_get_value();
+ }
+ static PyObject* remmina_pref_pyton_get_scale_quality() {
+ remmina_pref_get_scale_quality();
+ }
+ static PyObject* remmina_pref_pyton_get_sshtunnel_port() {
+ remmina_pref_get_sshtunnel_port();
+ }
+ static PyObject* remmina_pref_pyton_get_ssh_loglevel() {
+ remmina_pref_get_ssh_loglevel();
+ }
+ static PyObject* remmina_pref_pyton_get_ssh_parseconfig() {
+ remmina_pref_get_ssh_parseconfig();
+ }
+ static PyObject* remmina_pref_pyton_keymap_get_keyval() {
+ remmina_pref_keymap_get_keyval();
+ }
+
+ static PyObject* remmina_log_python_print() {
+ remmina_log_print();
+ }
+ static PyObject* remmina_log_python_printf() {
+ remmina_log_printf();
+ }
+
+ static PyObject* remmina_widget_python_pool_register() {
+ remmina_widget_pool_register();
+ }
+
+ static PyObject* rcw_open_python_from_file_full() {
+ rcw_open_from_file_full();
+ }
+
+ static PyObject* remmina_public_python_get_server_port() {
+ remmina_public_get_server_port();
+ }
+
+ static PyObject* remmina_masterthread_exec_python_is_main_thread() {
+ return remmina_masterthread_exec_is_main_thread();
+ }
+
+ static PyObject* remmina_gtksocket_available() {
+ remmina_gtksocket_available();
+ }
+
+ static PyObject* remmina_protocol_python_widget_get_profile_remote_width() {
+ remmina_protocol_widget_get_profile_remote_width();
+ }
+
+ static PyObject* remmina_protocol_python_widget_get_profile_remote_height() {
+ remmina_protocol_widget_get_profile_remote_height();
+ }
+};
+
+gboolean remmina_plugin_python_load(RemminaPluginService* service, const char* name) {
+ PyObject *pName, *pModule, *pFunc;
+ PyObject *pArgs, *pValue;
+ int i;
+
+ Py_Initialize();
+
+ PyRun_SimpleString("import sys");
+ PyRun_SimpleString("sys.path.append(\"/usr/local/lib/remmina/plugins\")");
+
+ pName = PyUnicode_DecodeFSDefault("toolsdevler");
+ /* Error checking of pName left out */
+
+ pModule = PyImport_Import(pName);
+ if (pModule != NULL) {
+ return TRUE;
+ } else {
+ PyErr_Print();
+ g_print("Failed to load \"%s\"\n", name);
+ return FALSE;
+ }
+ return TRUE;
+}
diff --git a/src/remmina_plugin_python.h b/src/remmina_plugin_python.h
new file mode 100644
index 000000000..4d1db6079
--- /dev/null
+++ b/src/remmina_plugin_python.h
@@ -0,0 +1,45 @@
+/*
+ * Remmina - The GTK+ Remote Desktop Client
+ * Copyright (C) 2010 Vic Lee
+ * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo
+ * Copyright (C) 2016-2020 Antenore Gatta, Giovanni Panozzo
+ *
+ * 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 02110-1301, USA.
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. * If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. * If you
+ * do not wish to do so, delete this exception statement from your
+ * version. * If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ *
+ */
+
+#pragma once
+
+#include "remmina_plugin_manager.h"
+
+G_BEGIN_DECLS
+
+gboolean remmina_plugin_python_load(RemminaPluginService* service, const char* name);
+
+G_END_DECLS