diff options
author | ToolsDevler <info@toolsdevler.net> | 2020-08-17 11:13:47 +0300 |
---|---|---|
committer | ToolsDevler <info@toolsdevler.net> | 2020-12-31 03:03:24 +0300 |
commit | 178758c8f95410936762f43867adea348fbd1dc7 (patch) | |
tree | 03b34e3e6372104af6e13238d6c63190da7531bd | |
parent | 7930213724f5f12fcf47fb8973cffad0ad871103 (diff) |
WIP: Python plugin implementation
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | plugins/common/remmina_plugin_python.h | 62 | ||||
-rw-r--r-- | src/CMakeLists.txt | 8 | ||||
-rw-r--r-- | src/remmina.c | 7 | ||||
-rw-r--r-- | src/remmina_plugin_manager.c | 63 | ||||
-rw-r--r-- | src/remmina_plugin_manager.h | 9 | ||||
-rw-r--r-- | src/remmina_plugin_native.c | 47 | ||||
-rw-r--r-- | src/remmina_plugin_native.h | 47 | ||||
-rw-r--r-- | src/remmina_plugin_python.c | 302 | ||||
-rw-r--r-- | src/remmina_plugin_python.h | 45 |
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 |