diff options
author | Mathias Winterhalter <2370037-ToolsDevler@users.noreply.gitlab.com> | 2022-04-30 01:21:52 +0300 |
---|---|---|
committer | Antenore Gatta (tmow) <antenore@simbiosi.org> | 2022-04-30 01:21:52 +0300 |
commit | faead9ed83c97c5260910f14b232dcb3f9c89d7b (patch) | |
tree | 5a1ef0d7fa6fcf258510361d63a7c4a89f47d620 /src | |
parent | 90f483b1afb43db0bc7f5e68f844931953bb185d (diff) |
Extract python plugin
Diffstat (limited to 'src')
27 files changed, 161 insertions, 4744 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a743f5d9a..8d7ddadbb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -141,50 +141,6 @@ set(RESOURCE_LIST ${CMAKE_CURRENT_SOURCE_DIR}/../data/ui/remmina_spinner.glade ${CMAKE_CURRENT_SOURCE_DIR}/../data/ui/remmina_string_list.glade ${CMAKE_CURRENT_SOURCE_DIR}/../data/ui/remmina_unlock.glade) - -option(WITH_PYTHONLIBS "Enable Python plugins support" OFF) -if(WITH_PYTHONLIBS) - message(STATUS "Python plugins support enabled") - find_suggested_package(PythonLibs) - if(PythonLibs_FOUND) - message(STATUS "Python libs found, Python support enabled") - add_definitions(-DWITH_PYTHONLIBS) - list(FIND REMMINA_SRCS "remmina_exec.c" SRCINDEX) - message(DEBUG "remmina_exec.c found at index: " ${SRCINDEX}) - # Index calculated at "remmina_exec.c" position (43 as of today) - list( - INSERT - REMMINA_SRCS - ${SRCINDEX} - "remmina_plugin_python.c" - "remmina_plugin_python.h" - "remmina_plugin_python_protocol.c" - "remmina_plugin_python_protocol.h" - "remmina_plugin_python_entry.c" - "remmina_plugin_python_entry.h" - "remmina_plugin_python_file.c" - "remmina_plugin_python_file.h" - "remmina_plugin_python_secret.c" - "remmina_plugin_python_secret.h" - "remmina_plugin_python_tool.c" - "remmina_plugin_python_tool.h" - "remmina_plugin_python_pref.c" - "remmina_plugin_python_pref.h" - "remmina_plugin_python_common.c" - "remmina_plugin_python_common.h" - "remmina_plugin_python_remmina.c" - "remmina_plugin_python_remmina.h" - "remmina_plugin_python_protocol_widget.c" - "remmina_plugin_python_protocol_widget.h" - "remmina_plugin_python_remmina_file.c" - "remmina_plugin_python_remmina_file.h") - else() - message(STATUS "Python plugins support enabled, but Python libs not found") - endif() -else() - message(STATUS "Python plugins support disabled") -endif() - message(DEBUG "Source list set to: " ${REMMINA_SRCS}) compile_gresources( diff --git a/src/include/remmina/plugin.h b/src/include/remmina/plugin.h index c75289af8..5f5b92e71 100644 --- a/src/include/remmina/plugin.h +++ b/src/include/remmina/plugin.h @@ -36,6 +36,7 @@ #pragma once +#include <gtk/gtk.h> #include <stdarg.h> #include <remmina/types.h> #include "remmina/remmina_trace_calls.h" @@ -48,7 +49,8 @@ typedef enum { REMMINA_PLUGIN_TYPE_FILE = 2, REMMINA_PLUGIN_TYPE_TOOL = 3, REMMINA_PLUGIN_TYPE_PREF = 4, - REMMINA_PLUGIN_TYPE_SECRET = 5 + REMMINA_PLUGIN_TYPE_SECRET = 5, + REMMINA_PLUGIN_TYPE_LANGUAGE_WRAPPER = 6 } RemminaPluginType; typedef struct _RemminaPlugin { @@ -145,6 +147,18 @@ typedef struct _RemminaSecretPlugin { void (*delete_password)(struct _RemminaSecretPlugin* instance, RemminaFile *remminafile, const gchar *key); } RemminaSecretPlugin; +typedef struct _RemminaLanguageWrapperPlugin { + RemminaPluginType type; + const gchar * name; + const gchar * description; + const gchar * domain; + const gchar * version; + const gchar ** supported_extentions; + + gboolean (*init)(struct _RemminaLanguageWrapperPlugin* instance); + gboolean (*load)(struct _RemminaLanguageWrapperPlugin* instance, const gchar* plugin_file); +} RemminaLanguageWrapperPlugin; + /* Plugin Service is a struct containing a list of function pointers, * which is passed from Remmina main program to the plugin module * through the plugin entry function remmina_plugin_entry() */ @@ -236,6 +250,56 @@ typedef struct _RemminaPluginService { gboolean (*gtksocket_available)(void); gint (*get_profile_remote_width)(RemminaProtocolWidget *gp); gint (*get_profile_remote_height)(RemminaProtocolWidget *gp); + const gchar*(*protocol_widget_get_name)(RemminaProtocolWidget *gp); + gint(*protocol_widget_get_width)(RemminaProtocolWidget *gp); + gint(*protocol_widget_get_height)(RemminaProtocolWidget *gp); + void(*protocol_widget_set_width)(RemminaProtocolWidget *gp, gint width); + void(*protocol_widget_set_height)(RemminaProtocolWidget *gp, gint height); + RemminaScaleMode(*protocol_widget_get_current_scale_mode)(RemminaProtocolWidget *gp); + gboolean (*protocol_widget_get_expand)(RemminaProtocolWidget *gp); + void (*protocol_widget_set_expand)(RemminaProtocolWidget *gp, gboolean expand); + void (*protocol_widget_set_error)(RemminaProtocolWidget *gp, const gchar *fmt, ...); + gboolean (*protocol_widget_has_error)(RemminaProtocolWidget *gp); + GtkWidget *(*protocol_widget_gtkviewport)(RemminaProtocolWidget *gp); + gboolean (*protocol_widget_is_closed)(RemminaProtocolWidget *gp); + RemminaFile *(*protocol_widget_get_file)(RemminaProtocolWidget *gp); + gint (*protocol_widget_panel_auth)(RemminaProtocolWidget *gp, RemminaMessagePanelFlags pflags, + const gchar *title, const gchar *default_username, const gchar *default_password, const gchar *default_domain, const gchar *password_prompt); + void (*protocol_widget_register_hostkey)(RemminaProtocolWidget *gp, GtkWidget *widget); + gchar *(*protocol_widget_start_direct_tunnel)(RemminaProtocolWidget *gp, gint default_port, gboolean port_plus); + gboolean (*protocol_widget_start_reverse_tunnel)(RemminaProtocolWidget *gp, gint local_port); + void (*protocol_widget_send_keys_signals)(GtkWidget *widget, const guint *keyvals, int keyvals_length, GdkEventType action); + void (*protocol_widget_chat_receive)(RemminaProtocolWidget *gp, const gchar *text); + void (*protocol_widget_panel_hide)(RemminaProtocolWidget *gp); + void (*protocol_widget_chat_open)(RemminaProtocolWidget *gp, const gchar *name, + void (*on_send)(RemminaProtocolWidget *gp, const gchar *text), void (*on_destroy)(RemminaProtocolWidget *gp)); + gboolean (*protocol_widget_ssh_exec)(RemminaProtocolWidget *gp, gboolean wait, const gchar *fmt, ...); + void (*protocol_widget_panel_show)(RemminaProtocolWidget *gp); + void (*protocol_widget_panel_show_retry)(RemminaProtocolWidget *gp); + gboolean (*protocol_widget_start_xport_tunnel)(RemminaProtocolWidget *gp, RemminaXPortTunnelInitFunc init_func); + void (*protocol_widget_set_display)(RemminaProtocolWidget *gp, gint display); + void (*protocol_widget_signal_connection_closed)(RemminaProtocolWidget *gp); + void (*protocol_widget_signal_connection_opened)(RemminaProtocolWidget *gp); + void (*protocol_widget_update_align)(RemminaProtocolWidget *gp); + void (*protocol_widget_unlock_dynres)(RemminaProtocolWidget *gp); + void (*protocol_widget_desktop_resize)(RemminaProtocolWidget *gp); + gint (*protocol_widget_panel_new_certificate)(RemminaProtocolWidget *gp, const gchar *subject, const gchar *issuer, const gchar *fingerprint); + gint (*protocol_widget_panel_changed_certificate)(RemminaProtocolWidget *gp, const gchar *subject, const gchar *issuer, const gchar *new_fingerprint, const gchar *old_fingerprint); + gchar *(*protocol_widget_get_username)(RemminaProtocolWidget *gp); + gchar *(*protocol_widget_get_password)(RemminaProtocolWidget *gp); + gchar *(*protocol_widget_get_domain)(RemminaProtocolWidget *gp); + gboolean (*protocol_widget_get_savepassword)(RemminaProtocolWidget *gp); + gint (*protocol_widget_panel_authx509)(RemminaProtocolWidget *gp); + gchar *(*protocol_widget_get_cacert)(RemminaProtocolWidget *gp); + gchar *(*protocol_widget_get_cacrl)(RemminaProtocolWidget *gp); + gchar *(*protocol_widget_get_clientcert)(RemminaProtocolWidget *gp); + gchar *(*protocol_widget_get_clientkey)(RemminaProtocolWidget *gp); + void (*protocol_widget_save_cred)(RemminaProtocolWidget *gp); + void (*protocol_widget_panel_show_listen)(RemminaProtocolWidget *gp, gint port); + void (*widget_pool_register)(GtkWidget *widget); + GtkWidget *(*rcw_open_from_file_full)(RemminaFile *remminafile, GCallback disconnect_cb, gpointer data, guint *handler); + void (*show_dialog)(GtkMessageType msg, GtkButtonsType buttons, const gchar* message); + GtkWindow *(*get_window)(void); } RemminaPluginService; /* "Prototype" of the plugin entry function */ diff --git a/src/remmina_plugin_manager.c b/src/remmina_plugin_manager.c index f61f236d4..98189a6eb 100644 --- a/src/remmina_plugin_manager.c +++ b/src/remmina_plugin_manager.c @@ -46,6 +46,7 @@ #include <gdk/gdkx.h> #include "remmina_public.h" +#include "remmina_main.h" #include "remmina_file_manager.h" #include "remmina_pref.h" #include "remmina_protocol_widget.h" @@ -54,9 +55,6 @@ #include "rcw.h" #include "remmina_plugin_manager.h" #include "remmina_plugin_native.h" -#ifdef WITH_PYTHONLIBS -#include "remmina_plugin_python.h" -#endif #include "remmina_public.h" #include "remmina_masterthread_exec.h" #include "remmina/remmina_trace_calls.h" @@ -70,7 +68,7 @@ static GHashTable *encrypted_settings_cache = NULL; 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 }; +{ N_("Protocol"), N_("Entry"), N_("File"), N_("Tool"), N_("Preference"), N_("Secret"), N_("Language Wrapper"), NULL }; static gint remmina_plugin_manager_compare_func(RemminaPlugin **a, RemminaPlugin **b) { @@ -257,7 +255,55 @@ RemminaPluginService remmina_plugin_manager_service = remmina_masterthread_exec_is_main_thread, remmina_gtksocket_available, remmina_protocol_widget_get_profile_remote_width, - remmina_protocol_widget_get_profile_remote_height + remmina_protocol_widget_get_profile_remote_height, + remmina_protocol_widget_get_name, + remmina_protocol_widget_get_width, + remmina_protocol_widget_get_height, + remmina_protocol_widget_set_width, + remmina_protocol_widget_set_height, + remmina_protocol_widget_get_current_scale_mode, + remmina_protocol_widget_get_expand, + remmina_protocol_widget_set_expand, + remmina_protocol_widget_set_error, + remmina_protocol_widget_has_error, + remmina_protocol_widget_gtkviewport, + remmina_protocol_widget_is_closed, + remmina_protocol_widget_get_file, + remmina_protocol_widget_panel_auth, + remmina_protocol_widget_register_hostkey, + remmina_protocol_widget_start_direct_tunnel, + remmina_protocol_widget_start_reverse_tunnel, + remmina_protocol_widget_send_keys_signals, + remmina_protocol_widget_chat_receive, + remmina_protocol_widget_panel_hide, + remmina_protocol_widget_chat_open, + remmina_protocol_widget_ssh_exec, + remmina_protocol_widget_panel_show, + remmina_protocol_widget_panel_show_retry, + remmina_protocol_widget_start_xport_tunnel, + remmina_protocol_widget_set_display, + remmina_protocol_widget_signal_connection_closed, + remmina_protocol_widget_signal_connection_opened, + remmina_protocol_widget_update_align, + remmina_protocol_widget_unlock_dynres, + remmina_protocol_widget_desktop_resize, + remmina_protocol_widget_panel_new_certificate, + remmina_protocol_widget_panel_changed_certificate, + remmina_protocol_widget_get_username, + remmina_protocol_widget_get_password, + remmina_protocol_widget_get_domain, + remmina_protocol_widget_get_savepassword, + remmina_protocol_widget_panel_authx509, + remmina_protocol_widget_get_cacert, + remmina_protocol_widget_get_cacrl, + remmina_protocol_widget_get_clientcert, + remmina_protocol_widget_get_clientkey, + remmina_protocol_widget_save_cred, + remmina_protocol_widget_panel_show_listen, + remmina_widget_pool_register, + rcw_open_from_file_full, + remmina_main_show_dialog, + remmina_main_get_window, }; const char *get_filename_ext(const char *filename) { @@ -267,23 +313,6 @@ const char *get_filename_ext(const char *filename) { return dot + 1; } -static void remmina_plugin_manager_load_plugin(const gchar *name) -{ - const char* ext = get_filename_ext(name); - - if (g_str_equal(G_MODULE_SUFFIX, ext)) { - remmina_plugin_native_load(&remmina_plugin_manager_service, name); - } else if (g_str_equal("py", ext)) { -#ifdef WITH_PYTHONLIBS - remmina_plugin_python_load(&remmina_plugin_manager_service, name); -#else - REMMINA_DEBUG("Python support not compiled, cannot load Python plugins"); -#endif - } else { - g_print("%s: Skip unsupported file type '%s'\n", name, ext); - } -} - static gint compare_secret_plugin_init_order(gconstpointer a, gconstpointer b) { RemminaSecretPlugin *sa, *sb; @@ -306,14 +335,13 @@ void remmina_plugin_manager_init() gchar *fullpath; RemminaPlugin *plugin; RemminaSecretPlugin *sp; - int i; + int i, j; GSList *secret_plugins; GSList *sple; + GPtrArray *alternative_language_plugins; remmina_plugin_table = g_ptr_array_new(); -#ifdef WITH_PYTHONLIBS - remmina_plugin_python_init(); -#endif + alternative_language_plugins = g_ptr_array_new(); if (!g_module_supported()) { g_print("Dynamic loading of plugins is not supported on this platform!\n"); @@ -329,14 +357,46 @@ void remmina_plugin_manager_init() if ((ptr = strrchr(name, '.')) == NULL) continue; ptr++; - if (!remmina_plugin_manager_loader_supported(ptr)) - continue; fullpath = g_strdup_printf(REMMINA_RUNTIME_PLUGINDIR "/%s", name); - remmina_plugin_manager_load_plugin(fullpath); + if (!remmina_plugin_manager_loader_supported(ptr)) { + g_ptr_array_add(alternative_language_plugins, g_strdup_printf(REMMINA_RUNTIME_PLUGINDIR "/%s", name)); + continue; + } + remmina_plugin_native_load(&remmina_plugin_manager_service, fullpath); g_free(fullpath); } g_dir_close(dir); + while (alternative_language_plugins->len > 0) { + gboolean has_loaded = FALSE; + gchar* name = (gchar*)g_ptr_array_remove_index(alternative_language_plugins, 0); + const gchar* ext = get_filename_ext(name); + + for (j = 0; j < remmina_plugin_table->len && !has_loaded; j++) { + plugin = (RemminaPlugin*)g_ptr_array_index(remmina_plugin_table, j); + if (plugin->type == REMMINA_PLUGIN_TYPE_LANGUAGE_WRAPPER) { + RemminaLanguageWrapperPlugin* wrapper_plugin = (RemminaLanguageWrapperPlugin*)plugin; + const gchar** supported_extention = wrapper_plugin->supported_extentions; + while (*supported_extention) { + if (g_str_equal(*supported_extention, ext)) { + has_loaded = wrapper_plugin->load(wrapper_plugin, name); + if (has_loaded) { + break; + } + } + supported_extention++; + } + if (has_loaded) break; + } + } + + if (!has_loaded) { + g_print("%s: Skip unsupported file type '%s'\n", name, ext); + } + + g_free(name); + } + /* Now all secret plugins needs to initialize, following their init_order. * The 1st plugin which will initialize correctly will be * the default remmina_secret_plugin */ @@ -369,7 +429,7 @@ void remmina_plugin_manager_init() gboolean remmina_plugin_manager_loader_supported(const char *filetype) { TRACE_CALL(__func__); - return g_str_equal("py", filetype) || g_str_equal(G_MODULE_SUFFIX, filetype); + return g_str_equal(G_MODULE_SUFFIX, filetype); } RemminaPlugin* remmina_plugin_manager_get_plugin(RemminaPluginType type, const gchar *name) diff --git a/src/remmina_plugin_python.c b/src/remmina_plugin_python.c deleted file mode 100644 index be83a4635..000000000 --- a/src/remmina_plugin_python.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Remmina - The GTK+ Remote Desktop Client - * Copyright (C) 2014-2022 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. - */ - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// I N C L U D E S -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#include "config.h" -#include "remmina/remmina_trace_calls.h" -#include "remmina_plugin_python_common.h" -#include "remmina_plugin_python.h" -#include "remmina_plugin_python_remmina.h" -#include "remmina_plugin_python_protocol_widget.h" - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// D E C L A R A T I O N S -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * An null terminated array of commands that are executed after the initialization of the Python engine. Every entry - * represents a line of Python code. - */ -static const char - * python_init_commands[] = { "import sys", "sys.path.append('" REMMINA_RUNTIME_PLUGINDIR "')", NULL // Sentinel -}; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// U T I L S -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * @brief Extracts the filename without extension from a path. - * - * @param in The string to extract the filename from - * @param out The resulting filename without extension (must point to allocated memory). - * - * @return The length of the filename extracted. - */ -static int basename_no_ext(const char* in, char** out) -{ - TRACE_CALL(__func__); - - assert(in); - assert(out); - - const char* base = strrchr(in, '/'); - if (base) - { - base++; - } - - const char* base_end = strrchr(base, '.'); - if (!base_end) - { - base_end = base + strlen(base); - } - - const int length = base_end - base; - const int memsize = sizeof(char*) * ((length) + 1); - - *out = (char*)remmina_plugin_python_malloc(memsize); - - memset(*out, 0, memsize); - strncpy(*out, base, length); - (*out)[length] = '\0'; - - return length; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// A P I -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -void remmina_plugin_python_init(void) -{ - TRACE_CALL(__func__); - - remmina_plugin_python_module_init(); - Py_Initialize(); - - for (const char** ptr = python_init_commands; *ptr; ++ptr) - { - PyRun_SimpleString(*ptr); - } - - remmina_plugin_python_protocol_widget_init(); -} - -gboolean remmina_plugin_python_load(RemminaPluginService* service, const char* name) -{ - TRACE_CALL(__func__); - - assert(service); - assert(name); - - remmina_plugin_python_set_service(service); - - char* filename = NULL; - if (basename_no_ext(name, &filename) == 0) - { - g_printerr("[%s:%d]: Can not extract filename from '%s'!\n", __FILE__, __LINE__, name); - return FALSE; - } - - PyObject* plugin_name = PyUnicode_DecodeFSDefault(filename); - - if (!plugin_name) - { - free(filename); - g_printerr("[%s:%d]: Error converting plugin filename to PyUnicode!\n", __FILE__, __LINE__); - return FALSE; - } - - wchar_t* program_name = NULL; - Py_ssize_t len = PyUnicode_AsWideChar(plugin_name, program_name, 0); - if (len <= 0) - { - free(filename); - g_printerr("[%s:%d]: Failed allocating %lu bytes!\n", __FILE__, __LINE__, (sizeof(wchar_t) * len)); - return FALSE; - } - - program_name = (wchar_t*)remmina_plugin_python_malloc(sizeof(wchar_t) * len); - if (!program_name) - { - free(filename); - g_printerr("[%s:%d]: Failed allocating %lu bytes!\n", __FILE__, __LINE__, (sizeof(wchar_t) * len)); - return FALSE; - } - - PyUnicode_AsWideChar(plugin_name, program_name, len); - - PySys_SetArgv(1, &program_name); - - if (PyImport_Import(plugin_name)) - { - free(filename); - return TRUE; - } - - g_print("[%s:%d]: Failed to load python plugin file: '%s'\n", __FILE__, __LINE__, name); - PyErr_Print(); - free(filename); - - return FALSE; -} diff --git a/src/remmina_plugin_python.h b/src/remmina_plugin_python.h deleted file mode 100644 index 97f53768d..000000000 --- a/src/remmina_plugin_python.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Remmina - The GTK+ Remote Desktop Client - * Copyright (C) 2014-2022 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. - */ - -/** - * @file remmina_plugin_python.h - * - * @brief Declares the interface between the Python plugin implementation and Remmina covering the initialization of - * the implementation and the load function, that allows Remmina to load plugins into the application. - * - * @details When Remmina discovers Python scripts in the plugin root folder the plugin manager passes the path to the - * Python plugin loader. There it gets executed and the plugin classes get mapped to "real" Remmina plugin - * instances. - * - * For the communication between Remmina and Python the python module called 'remmina' is initialized and - * loaded into the environment of the plugin script (@see remmina_plugin_python_module.c). - * - * @see http://www.remmina.org/wp for more information. - */ - -#pragma once - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// I N C L U D E -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#include "remmina/plugin.h" - -G_BEGIN_DECLS - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// A P I -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * @brief Initializes the Python plugin loaders. - * @details This does not load any plugins but initializes the implementation (e.g. globals and the Python engine). - */ -void remmina_plugin_python_init(void); - -/** - * @brief Loads a plugin from the Remmina plugin folder with the given name. - * - * @param service The instance of the service providing an API between Remmina and its plugins. - * @param filename The filename of the plugin to load. - * - * @return TRUE on success, FALSE otherwise. - */ -gboolean remmina_plugin_python_load(RemminaPluginService* service, const gchar* filename); - -G_END_DECLS diff --git a/src/remmina_plugin_python_common.c b/src/remmina_plugin_python_common.c deleted file mode 100644 index 527d96d6a..000000000 --- a/src/remmina_plugin_python_common.c +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Remmina - The GTK+ Remote Desktop Client - * Copyright (C) 2014-2021 Antenore Gatta, Giovanni Panozzo, Mathias Winterhalter (ToolsDevler) - * - * 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. - */ - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// I N C L U D E S -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#include "remmina_plugin_python_common.h" - -#include <assert.h> -#include <stdio.h> - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#include "pygobject.h" -#pragma GCC diagnostic pop - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// D E C L A R A T I O N S -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * A cache to store the last result that has been returned by the Python code using CallPythonMethod - * (@see remmina_plugin_python_common.h) - */ -static PyObject* __last_result; -static GPtrArray* plugin_map = NULL; - -static RemminaPluginService* remmina_plugin_service; - -const char* ATTR_NAME = "name"; -const char* ATTR_ICON_NAME = "icon_name"; -const char* ATTR_DESCRIPTION = "description"; -const char* ATTR_VERSION = "version"; -const char* ATTR_ICON_NAME_SSH = "icon_name_ssh"; -const char* ATTR_FEATURES = "features"; -const char* ATTR_BASIC_SETTINGS = "basic_settings"; -const char* ATTR_ADVANCED_SETTINGS = "advanced_settings"; -const char* ATTR_SSH_SETTING = "ssh_setting"; -const char* ATTR_EXPORT_HINTS = "export_hints"; -const char* ATTR_PREF_LABEL = "pref_label"; -const char* ATTR_INIT_ORDER = "init_order"; - -/** - * To prevent some memory related attacks or accidental allocation of an excessive amount of byes, this limit should - * always be used to check for a sane amount of bytes to allocate. - */ -static const int REASONABLE_LIMIT_FOR_MALLOC = 1024 * 1024; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// A P I -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -PyObject* remmina_plugin_python_last_result(void) -{ - TRACE_CALL(__func__); - - return __last_result; -} - -PyObject* remmina_plugin_python_last_result_set(PyObject* last_result) -{ - TRACE_CALL(__func__); - - return __last_result = last_result; -} - -gboolean remmina_plugin_python_check_error(void) -{ - TRACE_CALL(__func__); - - if (PyErr_Occurred()) - { - PyErr_Print(); - return TRUE; - } - - return FALSE; -} - -void remmina_plugin_python_log_method_call(PyObject* instance, const char* method) -{ - TRACE_CALL(__func__); - - assert(instance); - assert(method); - g_print("Python@%ld: %s.%s(...) -> %s\n", - PyObject_Hash(instance), - instance->ob_type->tp_name, - method, - PyUnicode_AsUTF8(PyObject_Str(remmina_plugin_python_last_result()))); -} - -long remmina_plugin_python_get_attribute_long(PyObject* instance, const char* attr_name, long def) -{ - TRACE_CALL(__func__); - - assert(instance); - assert(attr_name); - PyObject* attr = PyObject_GetAttrString(instance, attr_name); - if (attr && PyLong_Check(attr)) - { - return PyLong_AsLong(attr); - } - - return def; -} - -gboolean remmina_plugin_python_check_attribute(PyObject* instance, const char* attr_name) -{ - TRACE_CALL(__func__); - - assert(instance); - assert(attr_name); - if (PyObject_HasAttrString(instance, attr_name)) - { - return TRUE; - } - - g_printerr("Python plugin instance is missing member: %s\n", attr_name); - return FALSE; -} - -void* remmina_plugin_python_malloc(int bytes) -{ - TRACE_CALL(__func__); - - assert(bytes > 0); - assert(bytes <= REASONABLE_LIMIT_FOR_MALLOC); - - void* result = malloc(bytes); - - if (!result) - { - g_printerr("Unable to allocate %d bytes in memory!\n", bytes); - perror("malloc"); - } - - return result; -} - -char* remmina_plugin_python_copy_string_from_python(PyObject* string, Py_ssize_t len) -{ - TRACE_CALL(__func__); - - char* result = NULL; - if (len <= 0 || string == NULL) - { - return NULL; - } - - const char* py_str = PyUnicode_AsUTF8(string); - if (py_str) - { - const int label_size = sizeof(char) * (len + 1); - result = (char*)remmina_plugin_python_malloc(label_size); - result[len] = '\0'; - memcpy(result, py_str, len); - } - - return result; -} - -void remmina_plugin_python_set_service(RemminaPluginService* service) -{ - remmina_plugin_service = service; -} - -RemminaPluginService* remmina_plugin_python_get_service(void) -{ - return remmina_plugin_service; -} - -void remmina_plugin_python_add_plugin(PyPlugin* plugin) -{ - TRACE_CALL(__func__); - - if (!plugin_map) - { - plugin_map = g_ptr_array_new(); - } - - PyPlugin* test = remmina_plugin_python_get_plugin(plugin->generic_plugin->name); - if (test) - { - g_printerr("A plugin named '%s' has already been registered! Skipping...", plugin->generic_plugin->name); - } - else - { - g_ptr_array_add(plugin_map, plugin); - } -} - -RemminaTypeHint remmina_plugin_python_to_generic(PyObject* field, gpointer* target) -{ - TRACE_CALL(__func__); - - if (PyUnicode_Check(field)) - { - Py_ssize_t len = PyUnicode_GetLength(field); - - if (len > 0) - { - *target = remmina_plugin_python_copy_string_from_python(field, len); - } - else - { - *target = ""; - } - - return REMMINA_TYPEHINT_STRING; - } - else if (PyBool_Check(field)) - { - *target = remmina_plugin_python_malloc(sizeof(long)); - long* long_target = (long*)target; - *long_target = PyLong_AsLong(field); - return REMMINA_TYPEHINT_BOOLEAN; - } - else if (PyLong_Check(field)) - { - *target = remmina_plugin_python_malloc(sizeof(long)); - long* long_target = (long*)target; - *long_target = PyLong_AsLong(field); - return REMMINA_TYPEHINT_SIGNED; - } - else if (PyTuple_Check(field)) - { - Py_ssize_t len = PyTuple_Size(field); - if (len) - { - gpointer* dest = (gpointer*)remmina_plugin_python_malloc(sizeof(gpointer) * (len + 1)); - memset(dest, 0, sizeof(gpointer) * (len + 1)); - - for (Py_ssize_t i = 0; i < len; ++i) - { - PyObject* item = PyTuple_GetItem(field, i); - remmina_plugin_python_to_generic(item, dest + i); - } - - *target = dest; - } - return REMMINA_TYPEHINT_TUPLE; - } - - *target = NULL; - return REMMINA_TYPEHINT_UNDEFINED; -} - -PyPlugin* remmina_plugin_python_get_plugin(const char* name) -{ - TRACE_CALL(__func__); - - assert(plugin_map); - assert(name); - - for (gint i = 0; i < plugin_map->len; ++i) - { - PyPlugin* plugin = (PyPlugin*)g_ptr_array_index(plugin_map, i); - if (plugin->generic_plugin && plugin->generic_plugin->name && g_str_equal(name, plugin->generic_plugin->name)) - { - return plugin; - } - } - - return NULL; -} - -void init_pygobject() -{ - pygobject_init(-1, -1, -1); -} - -GtkWidget* new_pywidget(GObject* obj) -{ - return (GtkWidget*)pygobject_new(obj); -} - -GtkWidget* get_pywidget(PyObject* obj) -{ - return (GtkWidget*)pygobject_get(obj); -} diff --git a/src/remmina_plugin_python_common.h b/src/remmina_plugin_python_common.h deleted file mode 100644 index 21557bb65..000000000 --- a/src/remmina_plugin_python_common.h +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Remmina - The GTK+ Remote Desktop Client - * Copyright (C) 2014-2021 Antenore Gatta, Giovanni Panozzo, Mathias Winterhalter (ToolsDevler) - * - * 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. - */ - -/** - * @file remmina_plugin_python_common.h - * - * @brief Contains functions and constants that are commonly used throughout the Python plugin implementation. - * - * @details These functions should not be used outside of the Python plugin implementation, since everything is intended - * to be used with the Python engine. - */ - -#pragma once - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// I N C L U D E S -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#include <glib.h> -#include <gtk/gtk.h> - -#include <Python.h> -#include <glib.h> -#include <Python.h> -#include <structmember.h> - -#include "remmina/plugin.h" -#include "config.h" - - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// D E C L A R A T I O N S -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -G_BEGIN_DECLS - -// - Attribute names - -extern const char* ATTR_NAME; -extern const char* ATTR_ICON_NAME; -extern const char* ATTR_DESCRIPTION; -extern const char* ATTR_VERSION; -extern const char* ATTR_ICON_NAME_SSH; -extern const char* ATTR_FEATURES; -extern const char* ATTR_BASIC_SETTINGS; -extern const char* ATTR_ADVANCED_SETTINGS; -extern const char* ATTR_SSH_SETTING; -extern const char* ATTR_EXPORT_HINTS; -extern const char* ATTR_PREF_LABEL; -extern const char* ATTR_INIT_ORDER; - -// You can enable this for debuggin purposes or specify it in the build. -// #define WITH_PYTHON_TRACE_CALLS - -/** - * If WITH_PYTHON_TRACE_CALLS is defined, it logs the calls to the Python code and errors in case. - */ -#ifdef WITH_PYTHON_TRACE_CALLS -#define CallPythonMethod(instance, name, params, ...) \ - remmina_plugin_python_last_result_set(PyObject_CallMethod(instance, name, params, ##__VA_ARGS__)); \ - remmina_plugin_python_log_method_call(instance, name); \ - remmina_plugin_python_check_error() -#else -/** - * If WITH_TRACE_CALL is not defined, it still logs errors but doesn't print the call anymore. - */ -#define CallPythonMethod(instance, name, params, ...) \ - PyObject_CallMethod(instance, name, params, ##__VA_ARGS__); \ - remmina_plugin_python_check_error() -#endif // WITH_PYTHON_TRACE_CALLS - - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// T Y P E S -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * @brief The Python abstraction of the protocol widget struct. - * - * @details This struct is responsible to provide the same accessibility to the protocol widget for Python as for - * native plugins. - */ -typedef struct -{ - PyObject_HEAD - RemminaProtocolWidget* gp; -} PyRemminaProtocolWidget; - -/** - * @brief Maps an instance of a Python plugin to a Remmina one. - * - * @details This is used to map a Python plugin instance to the Remmina plugin one. Also instance specific data as the - * protocol widget are stored in this struct. - */ -typedef struct -{ - RemminaProtocolPlugin* protocol_plugin; - RemminaFilePlugin* file_plugin; - RemminaSecretPlugin* secret_plugin; - RemminaToolPlugin* tool_plugin; - RemminaEntryPlugin* entry_plugin; - RemminaPrefPlugin* pref_plugin; - RemminaPlugin* generic_plugin; - PyRemminaProtocolWidget* gp; - PyObject* instance; -} PyPlugin; - -/** - * A struct used to communicate data between Python and C without strict data type. - */ -typedef struct -{ - PyObject_HEAD; - RemminaTypeHint type_hint; - gpointer raw; -} PyGeneric; - -/** - * Checks if self is set and returns NULL if not. - */ -#define SELF_CHECK() if (!self) { \ - g_printerr("[%s:%d]: self is null!\n", __FILE__, __LINE__); \ - PyErr_SetString(PyExc_RuntimeError, "Method is not called from an instance (self is null)!"); \ - return NULL; \ - } - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// A P I -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * Creates a new instance of PyGeneric. - */ -PyGeneric* remmina_plugin_python_generic_new(void); - -/** - * Registers the given plugin if no other plugin with the same name has been already registered. - */ -void remmina_plugin_python_add_plugin(PyPlugin* plugin); - -/** - * Sets the pointer to the plugin service of Remmina. - */ -void remmina_plugin_python_set_service(RemminaPluginService* service); - -/** - * Extracts data from a PyObject instance to a generic pointer and returns a type hint if it could be determined. - */ -RemminaTypeHint remmina_plugin_python_to_generic(PyObject* field, gpointer* target); - -/** - * Gets the result of the last python method call. - */ -PyObject* remmina_plugin_python_last_result(void); - -/** - * @brief Sets the result of the last python method call. - * - * @return Returns the passed result (it's done to be compatible with the CallPythonMethod macro). - */ -PyObject* remmina_plugin_python_last_result_set(PyObject* result); - -/** - * @brief Prints a log message to inform the user a python message has been called. - * - * @detail This method is called from the CALL_PYTHON macro if WITH_PYTHON_TRACE_CALLS is defined. - * - * @param instance The instance that contains the called method. - * @param method The name of the method called. - */ -void remmina_plugin_python_log_method_call(PyObject* instance, const char* method); - -/** - * @brief Checks if an error has occurred and prints it. - * - * @return Returns TRUE if an error has occurred. - */ -gboolean remmina_plugin_python_check_error(void); - -/** - * @brief Gets the attribute as long value. - * - * @param instance The instance of the object to get the attribute. - * @param constant_name The name of the attribute to get. - * @param def The value to return if the attribute doesn't exist or is not set. - * - * @return The value attribute as long. - */ -long remmina_plugin_python_get_attribute_long(PyObject* instance, const char* attr_name, long def); - -/** - * @brief Checks if a given attribute exists. - * - * @param instance The object to check for the attribute. - * @param attr_name The name of the attribute to check. - * - * @return Returns TRUE if the attribute exists. - */ -gboolean remmina_plugin_python_check_attribute(PyObject* instance, const char* attr_name); - -/** - * @brief Allocates memory and checks for errors before returning. - * - * @param bytes Amount of bytes to allocate. - * - * @return Address to the allocated memory. - */ -void* remmina_plugin_python_malloc(int bytes); - -/** - * @biref Copies a string from a Python object to a new point in memory. - * - * @param string The python object, containing the string to copy. - * @param len The length of the string to copy. - * - * @return A char pointer to the new copy of the string. - */ -char* remmina_plugin_python_copy_string_from_python(PyObject* string, Py_ssize_t len); - -/** - * @brief Tries to find the Python plugin matching to the given instance of RemminaPlugin. - * - * @param plugin_map An array of PyPlugin pointers to search. - * @param instance The RemminaPlugin instance to find the correct PyPlugin instance for. - * - * @return A pointer to a PyPlugin instance if successful. Otherwise NULL is returned. - */ -PyPlugin* remmina_plugin_python_get_plugin(const char* name); - -/** - * Creates a new GtkWidget - * @param obj - * @return - */ -GtkWidget* new_pywidget(GObject* obj); - -/** - * Extracts a GtkWidget from a PyObject instance. - * @param obj - * @return - */ -GtkWidget* get_pywidget(PyObject* obj); - -/** - * Initializes the pygobject library. This needs to be called before any Python plugin is being initialized. - */ -void init_pygobject(void); - -G_END_DECLS diff --git a/src/remmina_plugin_python_entry.c b/src/remmina_plugin_python_entry.c deleted file mode 100644 index 54a478b18..000000000 --- a/src/remmina_plugin_python_entry.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Remmina - The GTK+ Remote Desktop Client - * Copyright (C) 2014-2021 Antenore Gatta, Giovanni Panozzo, Mathias Winterhalter (ToolsDevler) - * - * 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. - */ - -/** - * @file remmina_plugin_python_entry.c - * @brief Contains the wiring of a Python pluing based on RemminaPluginProtocol. - * @author Mathias Winterhalter - * @date 07.04.2021 - */ - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// I N C L U D E S -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#include "remmina_plugin_python_common.h" -#include "remmina_plugin_python_entry.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// D E C L A R A T I O N S -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// A P I -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -void remmina_plugin_python_entry_init(void) -{ - TRACE_CALL(__func__); -} - -void remmina_plugin_python_entry_entry_func_wrapper(RemminaEntryPlugin* instance) -{ - TRACE_CALL(__func__); - - PyPlugin* plugin = remmina_plugin_python_get_plugin(instance->name); - if (plugin) - { - CallPythonMethod(plugin->instance, "entry_func", NULL); - } -} - -RemminaPlugin* remmina_plugin_python_create_entry_plugin(PyPlugin* plugin) -{ - TRACE_CALL(__func__); - - PyObject* instance = plugin->instance; - - if (!remmina_plugin_python_check_attribute(instance, ATTR_NAME) - || !remmina_plugin_python_check_attribute(instance, ATTR_VERSION) - || !remmina_plugin_python_check_attribute(instance, ATTR_DESCRIPTION)) - { - g_printerr("Unable to create entry plugin. Aborting!\n"); - return NULL; - } - - RemminaEntryPlugin* remmina_plugin = (RemminaEntryPlugin*)remmina_plugin_python_malloc(sizeof(RemminaEntryPlugin)); - - remmina_plugin->type = REMMINA_PLUGIN_TYPE_ENTRY; - remmina_plugin->domain = GETTEXT_PACKAGE; - remmina_plugin->name = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_NAME)); - remmina_plugin->version = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_VERSION)); - remmina_plugin->description = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_DESCRIPTION)); - remmina_plugin->entry_func = remmina_plugin_python_entry_entry_func_wrapper; - - plugin->entry_plugin = remmina_plugin; - plugin->generic_plugin = (RemminaPlugin*)remmina_plugin; - - remmina_plugin_python_add_plugin(plugin); - - return (RemminaPlugin*)remmina_plugin; -} diff --git a/src/remmina_plugin_python_entry.h b/src/remmina_plugin_python_entry.h deleted file mode 100644 index 3b4c3ee38..000000000 --- a/src/remmina_plugin_python_entry.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Remmina - The GTK+ Remote Desktop Client - * Copyright (C) 2014-2021 Antenore Gatta, Giovanni Panozzo, Mathias Winterhalter (ToolsDevler) - * - * 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. - */ - -/** - * @file remmina_plugin_python_entry.h - * - * @brief Contains the specialisation of RemminaPluginEntry plugins in Python. - */ - -#pragma once - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// A P I -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -G_BEGIN_DECLS - -/** - * Initializes the Python plugin specialisation for entry plugins. - */ -void remmina_plugin_python_entry_init(void); - -/** - * @brief Creates a new instance of the RemminaPluginEntry, initializes its members and references the wrapper - * functions. - * @param instance The instance of the Python plugin. - * @return Returns a new instance of the RemminaPlugin (must be freed!). - */ -RemminaPlugin* remmina_plugin_python_create_entry_plugin(PyPlugin* instance); - -G_END_DECLS diff --git a/src/remmina_plugin_python_file.c b/src/remmina_plugin_python_file.c deleted file mode 100644 index 71a4dcd75..000000000 --- a/src/remmina_plugin_python_file.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Remmina - The GTK+ Remote Desktop Client - * Copyright (C) 2014-2021 Antenore Gatta, Giovanni Panozzo, Mathias Winterhalter (ToolsDevler) - * - * 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. - */ - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// I N C L U D E S -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#include "remmina_plugin_python_common.h" -#include "remmina_plugin_python_file.h" -#include "remmina_plugin_python_remmina_file.h" -#include "remmina_file.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// D E C L A R A T I O N S -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// A P I -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -void remmina_plugin_python_file_init(void) -{ - TRACE_CALL(__func__); -} - -gboolean remmina_plugin_python_file_import_test_func_wrapper(RemminaFilePlugin* instance, const gchar* from_file) -{ - TRACE_CALL(__func__); - - PyObject* result = NULL; - - PyPlugin* plugin = remmina_plugin_python_get_plugin(instance->name); - - if (plugin) - { - result = CallPythonMethod(plugin->instance, "import_test_func", "s", from_file); - } - - return result == Py_None || result != Py_False; -} - -RemminaFile* remmina_plugin_python_file_import_func_wrapper(RemminaFilePlugin* instance, const gchar* from_file) -{ - TRACE_CALL(__func__); - - PyObject* result = NULL; - - PyPlugin* plugin = remmina_plugin_python_get_plugin(instance->name); - if (!plugin) - { - return NULL; - } - - result = CallPythonMethod(plugin->instance, "import_func", "s", from_file); - - if (result == Py_None || result == Py_False) - { - return NULL; - } - - return ((PyRemminaFile*)result)->file; -} - -gboolean remmina_plugin_python_file_export_test_func_wrapper(RemminaFilePlugin* instance, RemminaFile* file) -{ - TRACE_CALL(__func__); - - PyObject* result = NULL; - - PyPlugin* plugin = remmina_plugin_python_get_plugin(instance->name); - if (plugin) - { - result = CallPythonMethod(plugin->instance, - "export_test_func", - "O", - remmina_plugin_python_remmina_file_to_python(file)); - } - - return result == Py_None || result != Py_False; -} - -gboolean -remmina_plugin_python_file_export_func_wrapper(RemminaFilePlugin* instance, RemminaFile* file, const gchar* to_file) -{ - TRACE_CALL(__func__); - - PyObject* result = NULL; - - PyPlugin* plugin = remmina_plugin_python_get_plugin(instance->name); - if (plugin) - { - result = CallPythonMethod(plugin->instance, "export_func", "s", to_file); - } - - return result == Py_None || result != Py_False; -} - -RemminaPlugin* remmina_plugin_python_create_file_plugin(PyPlugin* plugin) -{ - TRACE_CALL(__func__); - - PyObject* instance = plugin->instance; - Py_IncRef(instance); - - if (!remmina_plugin_python_check_attribute(instance, ATTR_NAME)) - { - g_printerr("Unable to create file plugin. Aborting!\n"); - return NULL; - } - - RemminaFilePlugin* remmina_plugin = (RemminaFilePlugin*)remmina_plugin_python_malloc(sizeof(RemminaFilePlugin)); - - remmina_plugin->type = REMMINA_PLUGIN_TYPE_FILE; - remmina_plugin->domain = GETTEXT_PACKAGE; - remmina_plugin->name = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_NAME)); - remmina_plugin->version = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_VERSION)); - remmina_plugin->description = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_DESCRIPTION)); - remmina_plugin->export_hints = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_EXPORT_HINTS)); - - remmina_plugin->import_test_func = remmina_plugin_python_file_import_test_func_wrapper; - remmina_plugin->import_func = remmina_plugin_python_file_import_func_wrapper; - remmina_plugin->export_test_func = remmina_plugin_python_file_export_test_func_wrapper; - remmina_plugin->export_func = remmina_plugin_python_file_export_func_wrapper; - - plugin->file_plugin = remmina_plugin; - plugin->generic_plugin = (RemminaPlugin*)remmina_plugin; - - remmina_plugin_python_add_plugin(plugin); - - return (RemminaPlugin*)remmina_plugin; -} diff --git a/src/remmina_plugin_python_file.h b/src/remmina_plugin_python_file.h deleted file mode 100644 index b45326f7f..000000000 --- a/src/remmina_plugin_python_file.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Remmina - The GTK+ Remote Desktop Client - * Copyright (C) 2014-2021 Antenore Gatta, Giovanni Panozzo, Mathias Winterhalter (ToolsDevler) - * - * 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. - */ - -/** - * @file remmina_plugin_python_file.h - * - * @brief Contains the specialisation of RemminaPluginFile plugins in Python. - */ - -#pragma once - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// A P I -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -G_BEGIN_DECLS - -/** - * Initializes the Python plugin specialisation for file plugins. - */ -void remmina_plugin_python_file_init(void); - -/** - * @brief Creates a new instance of the RemminaPluginFile, initializes its members and references the wrapper - * functions. - * @param instance The instance of the Python plugin. - * @return Returns a new instance of the RemminaPlugin (must be freed!). - */ -RemminaPlugin* remmina_plugin_python_create_file_plugin(PyPlugin* instance); - -G_END_DECLS diff --git a/src/remmina_plugin_python_pref.c b/src/remmina_plugin_python_pref.c deleted file mode 100644 index b799d105a..000000000 --- a/src/remmina_plugin_python_pref.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Remmina - The GTK+ Remote Desktop Client - * Copyright (C) 2014-2021 Antenore Gatta, Giovanni Panozzo, Mathias Winterhalter (ToolsDevler) - * - * 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. - */ - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// I N C L U D E S -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#include "remmina_plugin_python_common.h" -#include "remmina_plugin_python_pref.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// D E C L A R A T I O N S -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// A P I -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -void remmina_plugin_python_pref_init(void) -{ - TRACE_CALL(__func__); - -} - -/** - * @brief - */ -GtkWidget* remmina_plugin_python_pref_get_pref_body_wrapper(RemminaPrefPlugin* instance) -{ - TRACE_CALL(__func__); - - PyPlugin* plugin = remmina_plugin_python_get_plugin(instance->name); - - PyObject* result = CallPythonMethod(plugin->instance, "get_pref_body", NULL, NULL); - if (result == Py_None || result == NULL) - { - return NULL; - } - - return get_pywidget(result); -} - -RemminaPlugin* remmina_plugin_python_create_pref_plugin(PyPlugin* plugin) -{ - TRACE_CALL(__func__); - - PyObject* instance = plugin->instance; - - if (!remmina_plugin_python_check_attribute(instance, ATTR_NAME) - || !remmina_plugin_python_check_attribute(instance, ATTR_VERSION) - || !remmina_plugin_python_check_attribute(instance, ATTR_DESCRIPTION) - || !remmina_plugin_python_check_attribute(instance, ATTR_PREF_LABEL)) - { - g_printerr("Unable to create pref plugin. Aborting!\n"); - return NULL; - } - - RemminaPrefPlugin* remmina_plugin = (RemminaPrefPlugin*)remmina_plugin_python_malloc(sizeof(RemminaPrefPlugin)); - - remmina_plugin->type = REMMINA_PLUGIN_TYPE_PREF; - remmina_plugin->domain = GETTEXT_PACKAGE; - remmina_plugin->name = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_NAME)); - remmina_plugin->version = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_VERSION)); - remmina_plugin->description = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_DESCRIPTION)); - remmina_plugin->pref_label = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_PREF_LABEL)); - remmina_plugin->get_pref_body = remmina_plugin_python_pref_get_pref_body_wrapper; - - plugin->pref_plugin = remmina_plugin; - plugin->generic_plugin = (RemminaPlugin*)remmina_plugin; - - remmina_plugin_python_add_plugin(plugin); - - return (RemminaPlugin*)remmina_plugin; -} diff --git a/src/remmina_plugin_python_pref.h b/src/remmina_plugin_python_pref.h deleted file mode 100644 index ede1357ab..000000000 --- a/src/remmina_plugin_python_pref.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Remmina - The GTK+ Remote Desktop Client - * Copyright (C) 2014-2021 Antenore Gatta, Giovanni Panozzo, Mathias Winterhalter (ToolsDevler) - * - * 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. - */ - -/** - * @file remmina_plugin_python_pref.h - * - * @brief Contains the specialisation of RemminaPluginFile plugins in Python. - */ - -#pragma once - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// A P I -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -G_BEGIN_DECLS - -/** - * Initializes the Python plugin specialisation for preferences plugins. - */ -void remmina_plugin_python_pref_init(void); - -/** - * @brief Creates a new instance of the RemminaPluginPref, initializes its members and references the wrapper - * functions. - * @param instance The instance of the Python plugin. - * @return Returns a new instance of the RemminaPlugin (must be freed!). - */ -RemminaPlugin* remmina_plugin_python_create_pref_plugin(PyPlugin* instance); - -G_END_DECLS diff --git a/src/remmina_plugin_python_protocol.c b/src/remmina_plugin_python_protocol.c deleted file mode 100644 index d01b2a657..000000000 --- a/src/remmina_plugin_python_protocol.c +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Remmina - The GTK+ Remote Desktop Client - * Copyright (C) 2014-2022 Antenore Gatta, Giovanni Panozzo, Mathias Winterhalter (ToolsDevler) - * - * 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. - */ - -/** - * @file remmina_plugin_python_common.c - * @brief - * @author Mathias Winterhalter - * @date 07.04.2021 - */ - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// I N C L U D E S -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#include "remmina_plugin_python_common.h" -#include "remmina_plugin_python_protocol.h" -#include "remmina_plugin_python_remmina.h" - -#include "remmina_protocol_widget.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// D E C L A R A T I O N S -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// A P I -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -void remmina_plugin_python_protocol_init(void) -{ - TRACE_CALL(__func__); -} - -void remmina_protocol_init_wrapper(RemminaProtocolWidget* gp) -{ - TRACE_CALL(__func__); - PyPlugin* py_plugin = remmina_plugin_python_get_plugin(gp->plugin->name); - py_plugin->gp->gp = gp; - CallPythonMethod(py_plugin->instance, "init", "O", py_plugin->gp); -} - -gboolean remmina_protocol_open_connection_wrapper(RemminaProtocolWidget* gp) -{ - TRACE_CALL(__func__); - PyPlugin* py_plugin = remmina_plugin_python_get_plugin(gp->plugin->name); - if (py_plugin) - { - PyObject* result = CallPythonMethod(py_plugin->instance, "open_connection", "O", py_plugin->gp); - return result == Py_True; - } - else - { - return gtk_false(); - } -} - -gboolean remmina_protocol_close_connection_wrapper(RemminaProtocolWidget* gp) -{ - TRACE_CALL(__func__); - PyPlugin* py_plugin = remmina_plugin_python_get_plugin(gp->plugin->name); - PyObject* result = CallPythonMethod(py_plugin->instance, "close_connection", "O", py_plugin->gp); - return result == Py_True; -} - -gboolean remmina_protocol_query_feature_wrapper(RemminaProtocolWidget* gp, - const RemminaProtocolFeature* feature) -{ - TRACE_CALL(__func__); - PyPlugin* py_plugin = remmina_plugin_python_get_plugin(gp->plugin->name); - PyRemminaProtocolFeature* pyFeature = remmina_plugin_python_protocol_feature_new(); - pyFeature->type = (gint)feature->type; - pyFeature->id = feature->id; - pyFeature->opt1 = remmina_plugin_python_generic_new(); - pyFeature->opt1->raw = feature->opt1; - pyFeature->opt2 = remmina_plugin_python_generic_new(); - pyFeature->opt2->raw = feature->opt2; - pyFeature->opt3 = remmina_plugin_python_generic_new(); - pyFeature->opt3->raw = feature->opt3; - - PyObject* result = CallPythonMethod(py_plugin->instance, "query_feature", "OO", py_plugin->gp, pyFeature); - Py_DecRef((PyObject*)pyFeature); - Py_DecRef((PyObject*)pyFeature->opt1); - Py_DecRef((PyObject*)pyFeature->opt2); - Py_DecRef((PyObject*)pyFeature->opt3); - return result == Py_True; -} - -void remmina_protocol_call_feature_wrapper(RemminaProtocolWidget* gp, const RemminaProtocolFeature* feature) -{ - TRACE_CALL(__func__); - PyPlugin* py_plugin = remmina_plugin_python_get_plugin(gp->plugin->name); - PyRemminaProtocolFeature* pyFeature = remmina_plugin_python_protocol_feature_new(); - pyFeature->type = (gint)feature->type; - pyFeature->id = feature->id; - pyFeature->opt1 = remmina_plugin_python_generic_new(); - pyFeature->opt1->raw = feature->opt1; - pyFeature->opt1->type_hint = feature->opt1_type_hint; - pyFeature->opt2 = remmina_plugin_python_generic_new(); - pyFeature->opt2->raw = feature->opt2; - pyFeature->opt2->type_hint = feature->opt2_type_hint; - pyFeature->opt3 = remmina_plugin_python_generic_new(); - pyFeature->opt3->raw = feature->opt3; - pyFeature->opt3->type_hint = feature->opt3_type_hint; - - CallPythonMethod(py_plugin->instance, "call_feature", "OO", py_plugin->gp, pyFeature); - Py_DecRef((PyObject*)pyFeature); - Py_DecRef((PyObject*)pyFeature->opt1); - Py_DecRef((PyObject*)pyFeature->opt2); - Py_DecRef((PyObject*)pyFeature->opt3); -} - -void remmina_protocol_send_keytrokes_wrapper(RemminaProtocolWidget* gp, - const guint keystrokes[], - const gint keylen) -{ - TRACE_CALL(__func__); - PyPlugin* py_plugin = remmina_plugin_python_get_plugin(gp->plugin->name); - PyObject* obj = PyList_New(keylen); - Py_IncRef(obj); - for (int i = 0; i < keylen; ++i) - { - PyList_SetItem(obj, i, PyLong_FromLong(keystrokes[i])); - } - CallPythonMethod(py_plugin->instance, "send_keystrokes", "OO", py_plugin->gp, obj); - Py_DecRef(obj); -} - -gboolean remmina_protocol_get_plugin_screenshot_wrapper(RemminaProtocolWidget* gp, - RemminaPluginScreenshotData* rpsd) -{ - TRACE_CALL(__func__); - - PyPlugin* py_plugin = remmina_plugin_python_get_plugin(gp->plugin->name); - PyRemminaPluginScreenshotData* data = remmina_plugin_python_screenshot_data_new(); - Py_IncRef((PyObject*)data); - PyObject* result = CallPythonMethod(py_plugin->instance, "get_plugin_screenshot", "OO", py_plugin->gp, data); - if (result == Py_True) - { - if (!PyByteArray_Check((PyObject*)data->buffer)) - { - g_printerr("Unable to parse screenshot data. 'buffer' needs to be an byte array!"); - return 0; - } - Py_ssize_t buffer_len = PyByteArray_Size((PyObject*)data->buffer); - - // Is being freed by Remmina! - rpsd->buffer = (unsigned char*)remmina_plugin_python_malloc(sizeof(unsigned char) * buffer_len); - if (!rpsd->buffer) - { - return 0; - } - memcpy(rpsd->buffer, PyByteArray_AsString((PyObject*)data->buffer), sizeof(unsigned char) * buffer_len); - rpsd->bytesPerPixel = data->bytesPerPixel; - rpsd->bitsPerPixel = data->bitsPerPixel; - rpsd->height = data->height; - rpsd->width = data->width; - } - Py_DecRef((PyObject*)data->buffer); - Py_DecRef((PyObject*)data); - return result == Py_True; -} - -gboolean remmina_protocol_map_event_wrapper(RemminaProtocolWidget* gp) -{ - PyPlugin* plugin = remmina_plugin_python_get_plugin(gp->plugin->name); - PyObject* result = CallPythonMethod(plugin->instance, "map_event", "O", plugin->gp); - return PyBool_Check(result) && result == Py_True; -} - -gboolean remmina_protocol_unmap_event_wrapper(RemminaProtocolWidget* gp) -{ - PyPlugin* plugin = remmina_plugin_python_get_plugin(gp->plugin->name); - PyObject* result = CallPythonMethod(plugin->instance, "unmap_event", "O", plugin->gp); - return PyBool_Check(result) && result == Py_True; -} - -RemminaPlugin* remmina_plugin_python_create_protocol_plugin(PyPlugin* plugin) -{ - PyObject* instance = plugin->instance; - - if (!remmina_plugin_python_check_attribute(instance, ATTR_ICON_NAME_SSH) - || !remmina_plugin_python_check_attribute(instance, ATTR_ICON_NAME) - || !remmina_plugin_python_check_attribute(instance, ATTR_FEATURES) - || !remmina_plugin_python_check_attribute(instance, ATTR_BASIC_SETTINGS) - || !remmina_plugin_python_check_attribute(instance, ATTR_ADVANCED_SETTINGS) - || !remmina_plugin_python_check_attribute(instance, ATTR_SSH_SETTING)) - { - g_printerr("Unable to create protocol plugin. Aborting!\n"); - return NULL; - } - - RemminaProtocolPlugin* remmina_plugin = (RemminaProtocolPlugin*)remmina_plugin_python_malloc(sizeof(RemminaProtocolPlugin)); - - remmina_plugin->type = REMMINA_PLUGIN_TYPE_PROTOCOL; - remmina_plugin->domain = GETTEXT_PACKAGE; - remmina_plugin->basic_settings = NULL; - remmina_plugin->advanced_settings = NULL; - remmina_plugin->features = NULL; - - remmina_plugin->name = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_NAME)); - remmina_plugin->description = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_DESCRIPTION)); - remmina_plugin->version = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_VERSION)); - remmina_plugin->icon_name = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_ICON_NAME)); - remmina_plugin->icon_name_ssh = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_ICON_NAME_SSH)); - - PyObject* list = PyObject_GetAttrString(instance, "basic_settings"); - Py_ssize_t len = PyList_Size(list); - if (len) - { - RemminaProtocolSetting* basic_settings = (RemminaProtocolSetting*)remmina_plugin_python_malloc( - sizeof(RemminaProtocolSetting) * (len + 1)); - memset(basic_settings, 0, sizeof(RemminaProtocolSetting) * (len + 1)); - - for (Py_ssize_t i = 0; i < len; ++i) - { - RemminaProtocolSetting* dest = basic_settings + i; - remmina_plugin_python_to_protocol_setting(dest, PyList_GetItem(list, i)); - } - RemminaProtocolSetting* dest = basic_settings + len; - dest->type = REMMINA_PROTOCOL_SETTING_TYPE_END; - remmina_plugin->basic_settings = basic_settings; - } - - list = PyObject_GetAttrString(instance, "advanced_settings"); - len = PyList_Size(list); - if (len) - { - RemminaProtocolSetting* advanced_settings = (RemminaProtocolSetting*)remmina_plugin_python_malloc( - sizeof(RemminaProtocolSetting) * (len + 1)); - memset(advanced_settings, 0, sizeof(RemminaProtocolSetting) * (len + 1)); - - for (Py_ssize_t i = 0; i < len; ++i) - { - RemminaProtocolSetting* dest = advanced_settings + i; - remmina_plugin_python_to_protocol_setting(dest, PyList_GetItem(list, i)); - } - - RemminaProtocolSetting* dest = advanced_settings + len; - dest->type = REMMINA_PROTOCOL_SETTING_TYPE_END; - - remmina_plugin->advanced_settings = advanced_settings; - } - - list = PyObject_GetAttrString(instance, "features"); - len = PyList_Size(list); - if (len) - { - RemminaProtocolFeature* features = (RemminaProtocolFeature*)remmina_plugin_python_malloc( - sizeof(RemminaProtocolFeature) * (len + 1)); - memset(features, 0, sizeof(RemminaProtocolFeature) * (len + 1)); - - for (Py_ssize_t i = 0; i < len; ++i) - { - RemminaProtocolFeature* dest = features + i; - remmina_plugin_python_to_protocol_feature(dest, PyList_GetItem(list, i)); - } - - RemminaProtocolFeature* dest = features + len; - dest->type = REMMINA_PROTOCOL_FEATURE_TYPE_END; - - remmina_plugin->features = features; - } - - remmina_plugin->ssh_setting = (RemminaProtocolSSHSetting)remmina_plugin_python_get_attribute_long(instance, - ATTR_SSH_SETTING, - REMMINA_PROTOCOL_SSH_SETTING_NONE); - - remmina_plugin->init = remmina_protocol_init_wrapper; // Plugin initialization - remmina_plugin->open_connection = remmina_protocol_open_connection_wrapper; // Plugin open connection - remmina_plugin->close_connection = remmina_protocol_close_connection_wrapper; // Plugin close connection - remmina_plugin->query_feature = remmina_protocol_query_feature_wrapper; // Query for available features - remmina_plugin->call_feature = remmina_protocol_call_feature_wrapper; // Call a feature - remmina_plugin->send_keystrokes = - remmina_protocol_send_keytrokes_wrapper; // Send a keystroke - remmina_plugin->get_plugin_screenshot = - remmina_protocol_get_plugin_screenshot_wrapper; // Screenshot support unavailable - - remmina_plugin->map_event = remmina_protocol_map_event_wrapper; - remmina_plugin->unmap_event = remmina_protocol_unmap_event_wrapper; - - plugin->protocol_plugin = remmina_plugin; - plugin->generic_plugin = (RemminaPlugin*)remmina_plugin; - - remmina_plugin_python_add_plugin(plugin); - - return (RemminaPlugin*)remmina_plugin; -}
\ No newline at end of file diff --git a/src/remmina_plugin_python_protocol.h b/src/remmina_plugin_python_protocol.h deleted file mode 100644 index 42724dcc6..000000000 --- a/src/remmina_plugin_python_protocol.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Remmina - The GTK+ Remote Desktop Client - * Copyright (C) 2014-2022 Antenore Gatta, Giovanni Panozzo, Mathias Winterhalter (ToolsDevler) - * - * 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. - */ - -/** - * @file remmina_plugin_python_protocol.h - * - * @brief Contains the specialisation of RemminaPluginFile plugins in Python. - */ - -#pragma once - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// I N C L U D E S -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#include "remmina/plugin.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// A P I -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -G_BEGIN_DECLS - -/** - * Wrapper for a Python object that contains a pointer to an instance of RemminaProtocolFeature. - */ -typedef struct -{ - PyObject_HEAD - RemminaProtocolFeatureType type; - gint id; - PyGeneric* opt1; - PyGeneric* opt2; - PyGeneric* opt3; -} PyRemminaProtocolFeature; - -/** - * - */ -typedef struct -{ - PyObject_HEAD - PyByteArrayObject* buffer; - int bitsPerPixel; - int bytesPerPixel; - int width; - int height; -} PyRemminaPluginScreenshotData; - -/** - * Initializes the Python plugin specialisation for protocol plugins. - */ -void remmina_plugin_python_protocol_init(void); - -/** - * @brief Creates a new instance of the RemminaPluginProtocol, initializes its members and references the wrapper - * functions. - * - * @param instance The instance of the Python plugin. - * - * @return Returns a new instance of the RemminaPlugin (must be freed!). - */ -RemminaPlugin* remmina_plugin_python_create_protocol_plugin(PyPlugin* plugin); - -/** - * - * @return - */ -PyRemminaProtocolFeature* remmina_plugin_python_protocol_feature_new(void); - -/** - * - * @return - */ -PyRemminaPluginScreenshotData* remmina_plugin_python_screenshot_data_new(void); - -G_END_DECLS diff --git a/src/remmina_plugin_python_protocol_widget.c b/src/remmina_plugin_python_protocol_widget.c deleted file mode 100644 index eceb22422..000000000 --- a/src/remmina_plugin_python_protocol_widget.c +++ /dev/null @@ -1,846 +0,0 @@ -/* - * Remmina - The GTK+ Remote Desktop Client - * Copyright (C) 2014-2022 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. - */ - -/** - * @file remmina_plugin_python_protocol_widget.c - * @brief Implementation of the Protocol Widget API. - * @author Mathias Winterhalter - * @date 19.11.2020 - * - * The RemminaPluginService provides an API for plugins to interact with Remmina. The - * module called 'remmina' forwards this interface to make it accessible for Python - * scripts. - * - * This is an example of a minimal protocol plugin: - * - * @code - * import remmina - * - * class MyProtocol: - * def __init__(self): - * self.name = "MyProtocol" - * self.description = "Example protocol plugin to explain how Python plugins work." - * self.version = "0.1" - * self.icon_name = "" - * self.icon_name_ssh = "" - * - * def init(self, handle): - * print("This is getting logged to the standard output of Remmina.") - * remmina.log_print("For debugging purposes it would be better to log the output to the %s window %s!" % ("debug", ":)")) - * self.init_your_stuff(handle) - * - * def open_connection(self, handle): - * if not self.connect(): - * remmina.log_print("Error! Can not connect...") - * return False - * - * remmina.remmina_signal_connected(handle) - * remmina.log_print("Connection established!") - * return True - * - * - * def close_connection(self, handle): - * self.disconnect() - * return True - * - * plugin = MyProtocol() - * remmina.register_plugin(plugin) - * @endcode - * - * - * - * @see http://www.remmina.org/wp for more information. - */ - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// I N L U C E S -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#include "remmina_plugin_python_common.h" -#include "remmina/plugin.h" -#include "remmina_protocol_widget.h" -#include "remmina/types.h" -#include "remmina_plugin_python_remmina_file.h" -#include "remmina_plugin_python_protocol_widget.h" -#include "remmina_plugin_python_protocol.h" - -// -- Python Type -> RemminaWidget - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// D E C L A R A T I O N S -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -static PyObject* protocol_widget_get_viewport(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_get_width(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_set_width(PyRemminaProtocolWidget* self, PyObject* var_width); -static PyObject* protocol_widget_get_height(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_set_height(PyRemminaProtocolWidget* self, PyObject* var_height); -static PyObject* protocol_widget_get_current_scale_mode(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_get_expand(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_set_expand(PyRemminaProtocolWidget* self, PyObject* var_expand); -static PyObject* protocol_widget_has_error(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_set_error(PyRemminaProtocolWidget* self, PyObject* var_msg); -static PyObject* protocol_widget_is_closed(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_get_file(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_emit_signal(PyRemminaProtocolWidget* self, PyObject* var_signal); -static PyObject* protocol_widget_register_hostkey(PyRemminaProtocolWidget* self, PyObject* var_widget); -static PyObject* protocol_widget_start_direct_tunnel(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_start_reverse_tunnel(PyRemminaProtocolWidget* self, PyObject* var_local_port); -static PyObject* protocol_widget_start_xport_tunnel(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_set_display(PyRemminaProtocolWidget* self, PyObject* var_display); -static PyObject* protocol_widget_signal_connection_closed(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_signal_connection_opened(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_update_align(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_unlock_dynres(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_desktop_resize(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_panel_new_certificate(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_panel_changed_certificate(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_get_username(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_get_password(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_get_domain(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_get_savepassword(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_panel_authx509(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_get_cacert(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_get_cacrl(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_get_clientcert(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_get_clientkey(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_save_cred(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_panel_show_listen(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_panel_show_retry(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_panel_show(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_panel_hide(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_ssh_exec(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_chat_open(PyRemminaProtocolWidget* self, PyObject* var_name); -static PyObject* protocol_widget_chat_close(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_chat_receive(PyRemminaProtocolWidget* self, PyObject* args); -static PyObject* protocol_widget_send_keys_signals(PyRemminaProtocolWidget* self, PyObject* args); - -static struct PyMethodDef python_protocol_widget_type_methods[] = - {{ "get_viewport", (PyCFunction)protocol_widget_get_viewport, METH_NOARGS, "" }, - { "get_width", (PyCFunction)protocol_widget_get_width, METH_NOARGS, "" }, - { "set_width", (PyCFunction)protocol_widget_set_width, METH_VARARGS, "" }, - { "get_height", (PyCFunction)protocol_widget_get_height, METH_VARARGS, "" }, - { "set_height", (PyCFunction)protocol_widget_set_height, METH_VARARGS, "" }, - { "get_current_scale_mode", (PyCFunction)protocol_widget_get_current_scale_mode, METH_VARARGS, "" }, - { "get_expand", (PyCFunction)protocol_widget_get_expand, METH_VARARGS, "" }, - { "set_expand", (PyCFunction)protocol_widget_set_expand, METH_VARARGS, "" }, - { "has_error", (PyCFunction)protocol_widget_has_error, METH_VARARGS, "" }, - { "set_error", (PyCFunction)protocol_widget_set_error, METH_VARARGS, "" }, - { "is_closed", (PyCFunction)protocol_widget_is_closed, METH_VARARGS, "" }, - { "get_file", (PyCFunction)protocol_widget_get_file, METH_NOARGS, "" }, - { "emit_signal", (PyCFunction)protocol_widget_emit_signal, METH_VARARGS, "" }, - { "register_hostkey", (PyCFunction)protocol_widget_register_hostkey, METH_VARARGS, "" }, - { "start_direct_tunnel", (PyCFunction)protocol_widget_start_direct_tunnel, METH_VARARGS | METH_KEYWORDS, "" }, - { "start_reverse_tunnel", (PyCFunction)protocol_widget_start_reverse_tunnel, METH_VARARGS, "" }, - { "start_xport_tunnel", (PyCFunction)protocol_widget_start_xport_tunnel, METH_VARARGS, "" }, - { "set_display", (PyCFunction)protocol_widget_set_display, METH_VARARGS, "" }, - { "signal_connection_closed", (PyCFunction)protocol_widget_signal_connection_closed, METH_VARARGS, "" }, - { "signal_connection_opened", (PyCFunction)protocol_widget_signal_connection_opened, METH_VARARGS, "" }, - { "update_align", (PyCFunction)protocol_widget_update_align, METH_VARARGS, "" }, - { "unlock_dynres", (PyCFunction)protocol_widget_unlock_dynres, METH_VARARGS, "" }, - { "desktop_resize", (PyCFunction)protocol_widget_desktop_resize, METH_VARARGS, "" }, - { "panel_new_certificate", (PyCFunction)protocol_widget_panel_new_certificate, METH_VARARGS | METH_KEYWORDS, "" }, - { "panel_changed_certificate", (PyCFunction)protocol_widget_panel_changed_certificate, - METH_VARARGS | METH_KEYWORDS, "" }, - { "get_username", (PyCFunction)protocol_widget_get_username, METH_VARARGS, "" }, - { "get_password", (PyCFunction)protocol_widget_get_password, METH_VARARGS, "" }, - { "get_domain", (PyCFunction)protocol_widget_get_domain, METH_VARARGS, "" }, - { "get_savepassword", (PyCFunction)protocol_widget_get_savepassword, METH_VARARGS, "" }, - { "panel_authx509", (PyCFunction)protocol_widget_panel_authx509, METH_VARARGS, "" }, - { "get_cacert", (PyCFunction)protocol_widget_get_cacert, METH_VARARGS, "" }, - { "get_cacrl", (PyCFunction)protocol_widget_get_cacrl, METH_VARARGS, "" }, - { "get_clientcert", (PyCFunction)protocol_widget_get_clientcert, METH_VARARGS, "" }, - { "get_clientkey", (PyCFunction)protocol_widget_get_clientkey, METH_VARARGS, "" }, - { "save_cred", (PyCFunction)protocol_widget_save_cred, METH_VARARGS, "" }, - { "panel_show_listen", (PyCFunction)protocol_widget_panel_show_listen, METH_VARARGS, "" }, - { "panel_show_retry", (PyCFunction)protocol_widget_panel_show_retry, METH_VARARGS, "" }, - { "panel_show", (PyCFunction)protocol_widget_panel_show, METH_VARARGS, "" }, - { "panel_hide", (PyCFunction)protocol_widget_panel_hide, METH_VARARGS, "" }, - { "ssh_exec", (PyCFunction)protocol_widget_ssh_exec, METH_VARARGS | METH_KEYWORDS, "" }, - { "chat_open", (PyCFunction)protocol_widget_chat_open, METH_VARARGS, "" }, - { "chat_close", (PyCFunction)protocol_widget_chat_close, METH_VARARGS, "" }, - { "chat_receive", (PyCFunction)protocol_widget_chat_receive, METH_VARARGS, "" }, - { "send_keys_signals", (PyCFunction)protocol_widget_send_keys_signals, METH_VARARGS | METH_KEYWORDS, "" }, - { NULL }}; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// A P I -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -static PyObject* python_protocol_feature_new(PyTypeObject* type, PyObject* kws, PyObject* args) -{ - TRACE_CALL(__func__); - PyRemminaProtocolWidget* self; - self = (PyRemminaProtocolWidget*)type->tp_alloc(type, 0); - if (!self) - { - return NULL; - } - - return (PyObject*)self; -} - -static int python_protocol_feature_init(PyObject* self, PyObject* args, PyObject* kwds) -{ - return 0; -} - -static PyTypeObject python_protocol_widget_type = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "remmina.RemminaProtocolWidget", - .tp_doc = "RemminaProtocolWidget", - .tp_basicsize = sizeof(PyRemminaProtocolWidget), - .tp_itemsize = 0, - .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_new = python_protocol_feature_new, - .tp_init = python_protocol_feature_init, - .tp_methods = python_protocol_widget_type_methods -}; - -PyRemminaProtocolWidget* remmina_plugin_python_protocol_widget_create(void) -{ - TRACE_CALL(__func__); - - PyRemminaProtocolWidget* result = PyObject_NEW(PyRemminaProtocolWidget, &python_protocol_widget_type); - assert(result); - - PyErr_Print(); - Py_INCREF(result); - result->gp = NULL; - return result; -} - -void remmina_plugin_python_protocol_widget_init(void) -{ - init_pygobject(); -} - -void remmina_plugin_python_protocol_widget_type_ready(void) -{ - TRACE_CALL(__func__); - if (PyType_Ready(&python_protocol_widget_type) < 0) - { - g_printerr("Error initializing remmina.RemminaWidget!\n"); - PyErr_Print(); - } -} - -static PyObject* protocol_widget_get_viewport(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - return (PyObject*)new_pywidget(G_OBJECT(remmina_protocol_widget_gtkviewport(self->gp))); -} - -static PyObject* protocol_widget_get_width(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - return Py_BuildValue("i", remmina_protocol_widget_get_width(self->gp)); -} - -static PyObject* protocol_widget_set_width(PyRemminaProtocolWidget* self, PyObject* var_width) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - if (!var_width) - { - g_printerr("[%s:%d@%s]: Argument is null!\n", __FILE__, __LINE__, __func__); - return NULL; - } - - if (PyLong_Check(var_width)) - { - g_printerr("[%s:%d@%s]: Argument is not of type Long!\n", __FILE__, __LINE__, __func__); - return NULL; - } - - gint width = (gint)PyLong_AsLong(var_width); - remmina_protocol_widget_set_height(self->gp, width); - - return Py_None; -} - -static PyObject* protocol_widget_get_height(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - return Py_BuildValue("i", remmina_protocol_widget_get_height(self->gp)); -} - -static PyObject* protocol_widget_set_height(PyRemminaProtocolWidget* self, PyObject* var_height) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - if (!var_height) - { - g_printerr("[%s:%d@%s]: Argument is null!\n", __FILE__, __LINE__, __func__); - return NULL; - } - - if (PyLong_Check(var_height)) - { - g_printerr("[%s:%d@%s]: Argument is not of type Long!\n", __FILE__, __LINE__, __func__); - return NULL; - } - - gint height = (gint)PyLong_AsLong(var_height); - remmina_protocol_widget_set_height(self->gp, height); - - return Py_None; -} - -static PyObject* protocol_widget_get_current_scale_mode(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - return Py_BuildValue("i", remmina_protocol_widget_get_current_scale_mode(self->gp)); -} - -static PyObject* protocol_widget_get_expand(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - return Py_BuildValue("p", remmina_protocol_widget_get_expand(self->gp)); -} - -static PyObject* protocol_widget_set_expand(PyRemminaProtocolWidget* self, PyObject* var_expand) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - if (!var_expand) - { - g_printerr("[%s:%d@%s]: Argument is null!\n", __FILE__, __LINE__, __func__); - return NULL; - } - - if (PyBool_Check(var_expand)) - { - g_printerr("[%s:%d@%s]: Argument is not of type Boolean!\n", __FILE__, __LINE__, __func__); - return NULL; - } - - remmina_protocol_widget_set_expand(self->gp, PyObject_IsTrue(var_expand)); - - return Py_None; -} - -static PyObject* protocol_widget_has_error(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - return Py_BuildValue("p", remmina_protocol_widget_has_error(self->gp)); -} - -static PyObject* protocol_widget_set_error(PyRemminaProtocolWidget* self, PyObject* var_msg) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - if (!var_msg) - { - g_printerr("[%s:%d@%s]: Argument is null!\n", __FILE__, __LINE__, __func__); - return NULL; - } - - if (PyUnicode_Check(var_msg)) - { - g_printerr("[%s:%d@%s]: Argument is not of type String!\n", __FILE__, __LINE__, __func__); - return NULL; - } - - const gchar* msg = PyUnicode_AsUTF8(var_msg); - remmina_protocol_widget_set_error(self->gp, msg); - - return Py_None; -} - -static PyObject* protocol_widget_is_closed(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - return Py_BuildValue("p", remmina_protocol_widget_is_closed(self->gp)); -} - -static PyObject* protocol_widget_get_file(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - RemminaFile* file = remmina_protocol_widget_get_file(self->gp); - return (PyObject*)remmina_plugin_python_remmina_file_to_python(file); -} - -static PyObject* protocol_widget_emit_signal(PyRemminaProtocolWidget* self, PyObject* var_signal) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - if (!var_signal) - { - g_printerr("[%s:%d@%s]: Argument is null!\n", __FILE__, __LINE__, __func__); - return NULL; - } - - if (PyUnicode_Check(var_signal)) - { - g_printerr("[%s:%d@%s]: Argument is not of type String!\n", __FILE__, __LINE__, __func__); - return NULL; - } - - remmina_protocol_widget_set_error(self->gp, PyUnicode_AsUTF8(var_signal)); - - return Py_None; -} - -static PyObject* protocol_widget_register_hostkey(PyRemminaProtocolWidget* self, PyObject* var_widget) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - if (!var_widget) - { - g_printerr("[%s:%d@%s]: Argument is null!\n", __FILE__, __LINE__, __func__); - return NULL; - } - - remmina_protocol_widget_register_hostkey(self->gp, get_pywidget(var_widget)); - - return Py_None; -} - -static PyObject* protocol_widget_start_direct_tunnel(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - gint default_port; - gboolean port_plus; - - if (!args) - { - g_printerr("[%s:%d@%s]: Argument is null!\n", __FILE__, __LINE__, __func__); - } - - if (PyArg_ParseTuple(args, "ii", &default_port, &port_plus)) - { - return Py_BuildValue("s", remmina_protocol_widget_start_direct_tunnel(self->gp, default_port, port_plus)); - } - else - { - PyErr_Print(); - return NULL; - } - return Py_None; -} - -static PyObject* protocol_widget_start_reverse_tunnel(PyRemminaProtocolWidget* self, PyObject* var_local_port) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - if (!PyLong_Check(var_local_port)) - { - g_printerr("[%s:%d@%s]: Argument is null!\n", __FILE__, __LINE__, __func__); - return NULL; - } - - if (!PyLong_Check(var_local_port)) - { - g_printerr("[%s:%d@%s]: Argument is not of type Long!\n", __FILE__, __LINE__, __func__); - return NULL; - } - - return Py_BuildValue("p", remmina_protocol_widget_start_reverse_tunnel(self->gp, (gint)PyLong_AsLong(var_local_port))); -} - -static gboolean xport_tunnel_init(RemminaProtocolWidget* gp, gint remotedisplay, const gchar* server, gint port) -{ - TRACE_CALL(__func__); - PyPlugin* plugin = remmina_plugin_python_get_plugin(gp->plugin->name); - PyObject* result = PyObject_CallMethod(plugin->instance, "xport_tunnel_init", "Oisi", gp, remotedisplay, server, port); - return PyObject_IsTrue(result); -} - -static PyObject* protocol_widget_start_xport_tunnel(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - return Py_BuildValue("p", remmina_protocol_widget_start_xport_tunnel(self->gp, xport_tunnel_init)); -} - -static PyObject* protocol_widget_set_display(PyRemminaProtocolWidget* self, PyObject* var_display) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - if (!var_display) - { - g_printerr("[%s:%d@%s]: Argument is null!\n", __FILE__, __LINE__, __func__); - return NULL; - } - - if (!PyLong_Check(var_display)) - { - g_printerr("[%s:%d@%s]: Argument is not of type Long!\n", __FILE__, __LINE__, __func__); - return NULL; - } - - remmina_protocol_widget_set_display(self->gp, (gint)PyLong_AsLong(var_display)); - - return Py_None; -} - -static PyObject* protocol_widget_signal_connection_closed(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - remmina_protocol_widget_signal_connection_closed(self->gp); - return Py_None; -} - -static PyObject* protocol_widget_signal_connection_opened(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - remmina_protocol_widget_signal_connection_opened(self->gp); - return Py_None; -} - -static PyObject* protocol_widget_update_align(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - remmina_protocol_widget_update_align(self->gp); - return Py_None; -} - -static PyObject* protocol_widget_unlock_dynres(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - remmina_protocol_widget_unlock_dynres(self->gp); - return Py_None; -} - -static PyObject* protocol_widget_desktop_resize(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - remmina_protocol_widget_desktop_resize(self->gp); - return Py_None; -} - -static PyObject* protocol_widget_panel_new_certificate(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - gchar* subject, * issuer, * fingerprint; - - if (PyArg_ParseTuple(args, "sss", &subject, &issuer, &fingerprint)) - { - remmina_protocol_widget_panel_new_certificate(self->gp, subject, issuer, fingerprint); - } - else - { - PyErr_Print(); - return NULL; - } - return Py_None; -} - -static PyObject* protocol_widget_panel_changed_certificate(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - gchar* subject, * issuer, * new_fingerprint, * old_fingerprint; - - if (PyArg_ParseTuple(args, "sss", &subject, &issuer, &new_fingerprint, &old_fingerprint)) - { - remmina_protocol_widget_panel_changed_certificate(self->gp, subject, issuer, new_fingerprint, old_fingerprint); - } - else - { - PyErr_Print(); - return NULL; - } - return Py_None; -} - -static PyObject* protocol_widget_get_username(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - return Py_BuildValue("s", remmina_protocol_widget_get_username(self->gp)); -} - -static PyObject* protocol_widget_get_password(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - return Py_BuildValue("s", remmina_protocol_widget_get_password(self->gp)); -} - -static PyObject* protocol_widget_get_domain(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - return Py_BuildValue("s", remmina_protocol_widget_get_domain(self->gp)); -} - -static PyObject* protocol_widget_get_savepassword(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - return Py_BuildValue("p", remmina_protocol_widget_get_savepassword(self->gp)); -} - -static PyObject* protocol_widget_panel_authx509(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - return Py_BuildValue("i", remmina_protocol_widget_panel_authx509(self->gp)); -} - -static PyObject* protocol_widget_get_cacert(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - return Py_BuildValue("s", remmina_protocol_widget_get_cacert(self->gp)); -} - -static PyObject* protocol_widget_get_cacrl(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - return Py_BuildValue("s", remmina_protocol_widget_get_cacrl(self->gp)); -} - -static PyObject* protocol_widget_get_clientcert(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - return Py_BuildValue("s", remmina_protocol_widget_get_clientcert(self->gp)); -} - -static PyObject* protocol_widget_get_clientkey(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - return Py_BuildValue("s", remmina_protocol_widget_get_clientkey(self->gp)); -} - -static PyObject* protocol_widget_save_cred(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - remmina_protocol_widget_save_cred(self->gp); - return Py_None; -} - -static PyObject* protocol_widget_panel_show_listen(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - gint port = 0; - - if (PyArg_ParseTuple(args, "i", &port)) - { - remmina_protocol_widget_panel_show_listen(self->gp, port); - } - else - { - PyErr_Print(); - return NULL; - } - return Py_None; -} - -static PyObject* protocol_widget_panel_show_retry(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - remmina_protocol_widget_panel_show_retry(self->gp); - return Py_None; -} - -static PyObject* protocol_widget_panel_show(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - remmina_protocol_widget_panel_show(self->gp); - return Py_None; -} - -static PyObject* protocol_widget_panel_hide(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - remmina_protocol_widget_panel_hide(self->gp); - return Py_None; -} - -static PyObject* protocol_widget_ssh_exec(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - gboolean wait; - gchar* cmd; - - if (PyArg_ParseTuple(args, "ps", &wait, &cmd)) - { - remmina_protocol_widget_ssh_exec(self->gp, wait, cmd); - } - else - { - PyErr_Print(); - return NULL; - } - return Py_None; -} - -static void _on_send_callback_wrapper(RemminaProtocolWidget* gp, const gchar* text) -{ - PyPlugin* plugin = remmina_plugin_python_get_plugin(gp->plugin->name); - PyObject_CallMethod(plugin->instance, "on_send", "Os", gp, text); -} - -static void _on_destroy_callback_wrapper(RemminaProtocolWidget* gp) -{ - PyPlugin* plugin = remmina_plugin_python_get_plugin(gp->plugin->name); - PyObject_CallMethod(plugin->instance, "on_destroy", "O", gp); -} - -static PyObject* protocol_widget_chat_open(PyRemminaProtocolWidget* self, PyObject* var_name) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - if (!PyUnicode_Check(var_name)) - { - g_printerr("[%s:%d@%s]: Argument is not of type String!\n", __FILE__, __LINE__, __func__); - } - - remmina_protocol_widget_chat_open(self->gp, - PyUnicode_AsUTF8(var_name), - _on_send_callback_wrapper, - _on_destroy_callback_wrapper); - - return Py_None; -} - -static PyObject* protocol_widget_chat_close(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - - remmina_protocol_widget_panel_hide(self->gp); - return Py_None; -} - -static PyObject* protocol_widget_chat_receive(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - gchar* text; - - if (PyArg_ParseTuple(args, "s", &text)) - { - remmina_protocol_widget_chat_receive(self->gp, text); - } - else - { - PyErr_Print(); - return NULL; - } - - return Py_None; -} - -static PyObject* protocol_widget_send_keys_signals(PyRemminaProtocolWidget* self, PyObject* args) -{ - TRACE_CALL(__func__); - SELF_CHECK(); - guint* keyvals; - int length; - GdkEventType event_type; - PyObject* widget; - - if (PyArg_ParseTuple(args, "Osii", &widget, &keyvals, &length, &event_type) && widget && keyvals) - { - if (event_type < GDK_NOTHING || event_type >= GDK_EVENT_LAST) - { - g_printerr("[%s:%d@%s]: %d is not a known value for GdkEventType!\n", __FILE__, __LINE__, __func__, event_type); - return NULL; - } - else - { - remmina_protocol_widget_send_keys_signals((GtkWidget*)widget, keyvals, length, event_type); - } - } - else - { - PyErr_Print(); - return NULL; - } - - return Py_None; -} diff --git a/src/remmina_plugin_python_protocol_widget.h b/src/remmina_plugin_python_protocol_widget.h deleted file mode 100644 index dcbbc8093..000000000 --- a/src/remmina_plugin_python_protocol_widget.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Remmina - The GTK+ Remote Desktop Client - * Copyright (C) 2016-2022 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. - */ - -/** - * @file remmina_plugin_python_protocol_widget.h - * - * @brief Contains the implementation of the widget handling used from the protocol plugin. - */ - -#pragma once - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// A P I -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -G_BEGIN_DECLS - -/** - * Initializes the widget backend of the protocol plugin implementation. - */ -void remmina_plugin_python_protocol_widget_init(void); - -/** - * Initializes Python types used for protocol widgets. - */ -void remmina_plugin_python_protocol_widget_type_ready(void); - -/** - * Creates a new instance of PyRemminaProtocolWidget and initializes its fields. - */ -PyRemminaProtocolWidget* remmina_plugin_python_protocol_widget_create(); - -G_END_DECLS diff --git a/src/remmina_plugin_python_remmina.c b/src/remmina_plugin_python_remmina.c deleted file mode 100644 index ad0ebc7a4..000000000 --- a/src/remmina_plugin_python_remmina.c +++ /dev/null @@ -1,1225 +0,0 @@ -/* - * Remmina - The GTK+ Remote Desktop Client - * Copyright (C) 2016-2022 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. - */ - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// I N C L U D E S -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#include "remmina_plugin_python_common.h" -#include "remmina_main.h" -#include "remmina_plugin_manager.h" -#include "remmina/plugin.h" -#include "remmina/types.h" -#include "remmina_protocol_widget.h" -#include "remmina_log.h" - -#include "remmina_plugin_python_remmina.h" -#include "remmina_plugin_python_protocol_widget.h" - -#include "remmina_plugin_python_entry.h" -#include "remmina_plugin_python_file.h" -#include "remmina_plugin_python_protocol.h" -#include "remmina_plugin_python_tool.h" -#include "remmina_plugin_python_secret.h" -#include "remmina_plugin_python_pref.h" - -#include "remmina_pref.h" -#include "remmina_ssh.h" -#include "remmina_file_manager.h" -#include "remmina_widget_pool.h" -#include "remmina_public.h" -#include "remmina_masterthread_exec.h" - -#include "rcw.h" -#include "remmina_plugin_python_remmina_file.h" - -#include <string.h> - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// D E C L A R A T I O N S -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - -/** - * Util function to check if a specific member is define in a Python object. - */ -gboolean remmina_plugin_python_check_mandatory_member(PyObject* instance, const gchar* member); - -static PyObject* remmina_plugin_python_debug_wrapper(PyObject* self, PyObject* msg); -static PyObject* remmina_register_plugin_wrapper(PyObject* self, PyObject* plugin); -static PyObject* remmina_file_get_datadir_wrapper(PyObject* self, PyObject* plugin); -static PyObject* remmina_file_new_wrapper(PyObject* self, PyObject* args, PyObject* kwargs); -static PyObject* remmina_pref_set_value_wrapper(PyObject* self, PyObject* args, PyObject* kwargs); -static PyObject* remmina_pref_get_value_wrapper(PyObject* self, PyObject* args, PyObject* kwargs); -static PyObject* remmina_pref_get_scale_quality_wrapper(PyObject* self, PyObject* plugin); -static PyObject* remmina_pref_get_sshtunnel_port_wrapper(PyObject* self, PyObject* plugin); -static PyObject* remmina_pref_get_ssh_loglevel_wrapper(PyObject* self, PyObject* plugin); -static PyObject* remmina_pref_get_ssh_parseconfig_wrapper(PyObject* self, PyObject* plugin); -static PyObject* remmina_pref_keymap_get_keyval_wrapper(PyObject* self, PyObject* args, PyObject* kwargs); -static PyObject* remmina_plugin_python_log_print_wrapper(PyObject* self, PyObject* arg); -static PyObject* remmina_widget_pool_register_wrapper(PyObject* self, PyObject* args, PyObject* kwargs); -static PyObject* rcw_open_from_file_full_wrapper(PyObject* self, PyObject* args, PyObject* kwargs); -static PyObject* remmina_public_get_server_port_wrapper(PyObject* self, PyObject* args, PyObject* kwargs); -static PyObject* remmina_masterthread_exec_is_main_thread_wrapper(PyObject* self, PyObject* plugin); -static PyObject* remmina_gtksocket_available_wrapper(PyObject* self, PyObject* plugin); -static PyObject* -remmina_protocol_widget_get_profile_remote_height_wrapper(PyObject* self, PyObject* args, PyObject* kwargs); -static PyObject* -remmina_protocol_widget_get_profile_remote_width_wrapper(PyObject* self, PyObject* args, PyObject* kwargs); -static PyObject* remmina_plugin_python_show_dialog_wrapper(PyObject* self, PyObject* args, PyObject* kwargs); -static PyObject* remmina_plugin_python_get_mainwindow_wrapper(PyObject* self, PyObject* args); -static PyObject* remmina_protocol_plugin_signal_connection_opened_wrapper(PyObject* self, PyObject* args); -static PyObject* remmina_protocol_plugin_signal_connection_closed_wrapper(PyObject* self, PyObject* args); -static PyObject* remmina_protocol_plugin_init_auth_wrapper(PyObject* self, PyObject* args, PyObject* kwargs); - -/** - * Declares functions for the Remmina module. These functions can be called from Python and are wired to one of the - * functions here in this file. - */ -static PyMethodDef remmina_python_module_type_methods[] = { - /** - * The first function that need to be called from the plugin code, since it registers the Python class acting as - * a Remmina plugin. Without this call the plugin will not be recognized. - */ - { "register_plugin", remmina_register_plugin_wrapper, METH_O, NULL }, - - /** - * Prints a string into the Remmina log infrastructure. - */ - { "log_print", remmina_plugin_python_log_print_wrapper, METH_VARARGS, NULL }, - - /** - * Prints a debug message if enabled. - */ - { "debug", remmina_plugin_python_debug_wrapper, METH_VARARGS, NULL }, - - /** - * Shows a GTK+ dialog. - */ - { "show_dialog", (PyCFunction)remmina_plugin_python_show_dialog_wrapper, METH_VARARGS | METH_KEYWORDS, - NULL }, - - /** - * Returns the GTK+ object of the main window of Remmina. - */ - { "get_main_window", remmina_plugin_python_get_mainwindow_wrapper, METH_NOARGS, NULL }, - - /** - * Calls remmina_file_get_datadir and returns its result. - */ - { "get_datadir", remmina_file_get_datadir_wrapper, METH_VARARGS, NULL }, - - /** - * Calls remmina_file_new and returns its result. - */ - { "file_new", (PyCFunction)remmina_file_new_wrapper, METH_VARARGS | METH_KEYWORDS, NULL }, - - /** - * Calls remmina_pref_set_value and returns its result. - */ - { "pref_set_value", (PyCFunction)remmina_pref_set_value_wrapper, METH_VARARGS | METH_KEYWORDS, NULL }, - - /** - * Calls remmina_pref_get_value and returns its result. - */ - { "pref_get_value", (PyCFunction)remmina_pref_get_value_wrapper, METH_VARARGS | METH_KEYWORDS, NULL }, - - /** - * Calls remmina_pref_get_scale_quality and returns its result. - */ - { "pref_get_scale_quality", remmina_pref_get_scale_quality_wrapper, METH_VARARGS, NULL }, - - /** - * Calls remmina_pref_get_sshtunnel_port and returns its result. - */ - { "pref_get_sshtunnel_port", remmina_pref_get_sshtunnel_port_wrapper, METH_VARARGS, NULL }, - - /** - * Calls remmina_pref_get_ssh_loglevel and returns its result. - */ - { "pref_get_ssh_loglevel", remmina_pref_get_ssh_loglevel_wrapper, METH_VARARGS, NULL }, - - /** - * Calls remmina_pref_get_ssh_parseconfig and returns its result. - */ - { "pref_get_ssh_parseconfig", remmina_pref_get_ssh_parseconfig_wrapper, METH_VARARGS, NULL }, - - /** - * Calls remmina_pref_keymap_get_keyval and returns its result. - */ - { "pref_keymap_get_keyval", (PyCFunction)remmina_pref_keymap_get_keyval_wrapper, METH_VARARGS | METH_KEYWORDS, - NULL }, - - /** - * Calls remmina_widget_pool_register and returns its result. - */ - { "widget_pool_register", (PyCFunction)remmina_widget_pool_register_wrapper, METH_VARARGS | METH_KEYWORDS, NULL }, - - /** - * Calls rcw_open_from_file_full and returns its result. - */ - { "rcw_open_from_file_full", (PyCFunction)rcw_open_from_file_full_wrapper, METH_VARARGS | METH_KEYWORDS, NULL }, - - /** - * Calls remmina_public_get_server_port and returns its result. - */ - { "public_get_server_port", (PyCFunction)remmina_public_get_server_port_wrapper, METH_VARARGS | METH_KEYWORDS, - NULL }, - - /** - * Calls remmina_masterthread_exec_is_main_thread and returns its result. - */ - { "masterthread_exec_is_main_thread", remmina_masterthread_exec_is_main_thread_wrapper, METH_VARARGS, NULL }, - - /** - * Calls remmina_gtksocket_available and returns its result. - */ - { "gtksocket_available", remmina_gtksocket_available_wrapper, METH_VARARGS, NULL }, - - /** - * Calls remmina_protocol_widget_get_profile_remote_width and returns its result. - */ - { "protocol_widget_get_profile_remote_width", - (PyCFunction)remmina_protocol_widget_get_profile_remote_width_wrapper, METH_VARARGS | METH_KEYWORDS, NULL }, - - /** - * Calls remmina_protocol_widget_get_profile_remote_height and returns its result. - */ - { "protocol_widget_get_profile_remote_height", - (PyCFunction)remmina_protocol_widget_get_profile_remote_height_wrapper, METH_VARARGS | METH_KEYWORDS, NULL }, - { "protocol_plugin_signal_connection_opened", (PyCFunction)remmina_protocol_plugin_signal_connection_opened_wrapper, - METH_VARARGS, NULL }, - - { "protocol_plugin_signal_connection_closed", (PyCFunction)remmina_protocol_plugin_signal_connection_closed_wrapper, - METH_VARARGS, NULL }, - - { "protocol_plugin_init_auth", (PyCFunction)remmina_protocol_plugin_init_auth_wrapper, METH_VARARGS | METH_KEYWORDS, - NULL }, - - /* Sentinel */ - { NULL } -}; - -/** - * Adapter struct to handle Remmina protocol settings. - */ -typedef struct -{ - PyObject_HEAD - RemminaProtocolSettingType settingType; - gchar* name; - gchar* label; - gboolean compact; - PyObject* opt1; - PyObject* opt2; -} PyRemminaProtocolSetting; - -/** - * The definition of the Python module 'remmina'. - */ -static PyModuleDef remmina_python_module_type = { - PyModuleDef_HEAD_INIT, - .m_name = "remmina", - .m_doc = "Remmina API.", - .m_size = -1, - .m_methods = remmina_python_module_type_methods -}; - -// -- Python Object -> Setting - -/** - * Initializes the memory and the fields of the remmina.Setting Python type. - * @details This function is callback for the Python engine. - */ -static PyObject* python_protocol_setting_new(PyTypeObject* type, PyObject* args, PyObject* kwargs) -{ - TRACE_CALL(__func__); - - PyRemminaProtocolSetting* self = (PyRemminaProtocolSetting*)type->tp_alloc(type, 0); - - if (!self) - { - return NULL; - } - - self->name = ""; - self->label = ""; - self->compact = FALSE; - self->opt1 = NULL; - self->opt2 = NULL; - self->settingType = 0; - - return (PyObject*)self; -} - -/** - * Constructor of the remmina.Setting Python type. - * @details This function is callback for the Python engine. - */ -static int python_protocol_setting_init(PyRemminaProtocolSetting* self, PyObject* args, PyObject* kwargs) -{ - TRACE_CALL(__func__); - - static gchar* kwlist[] = { "type", "name", "label", "compact", "opt1", "opt2", NULL }; - PyObject* name; - PyObject* label; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|lOOpOO", kwlist, - &self->settingType, &name, &label, &self->compact, &self->opt1, &self->opt2)) - { - return -1; - } - - Py_ssize_t len = PyUnicode_GetLength(label); - if (len == 0) - { - self->label = ""; - } - else - { - self->label = remmina_plugin_python_copy_string_from_python(label, len); - if (!self->label) - { - g_printerr("Unable to extract label during initialization of Python settings module!\n"); - remmina_plugin_python_check_error(); - } - } - - len = PyUnicode_GetLength(name); - if (len == 0) - { - self->name = ""; - } - else - { - self->name = remmina_plugin_python_copy_string_from_python(label, len); - if (!self->name) - { - g_printerr("Unable to extract name during initialization of Python settings module!\n"); - remmina_plugin_python_check_error(); - } - } - - return 0; -} - -static PyMemberDef python_protocol_setting_type_members[] = { - { "settingType", offsetof(PyRemminaProtocolSetting, settingType), T_INT, 0, NULL }, - { "name", offsetof(PyRemminaProtocolSetting, name), T_STRING, 0, NULL }, - { "label", offsetof(PyRemminaProtocolSetting, label), T_STRING, 0, NULL }, - { "compact", offsetof(PyRemminaProtocolSetting, compact), T_BOOL, 0, NULL }, - { "opt1", offsetof(PyRemminaProtocolSetting, opt1), T_OBJECT, 0, NULL }, - { "opt2", offsetof(PyRemminaProtocolSetting, opt2), T_OBJECT, 0, NULL }, - { NULL } -}; - -static PyTypeObject python_protocol_setting_type = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "remmina.Setting", - .tp_doc = "Remmina Setting information", - .tp_basicsize = sizeof(PyRemminaProtocolSetting), - .tp_itemsize = 0, - .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_new = python_protocol_setting_new, - .tp_init = (initproc)python_protocol_setting_init, - .tp_members = python_protocol_setting_type_members -}; - -// -- Python Type -> Feature - - -static PyMemberDef python_protocol_feature_members[] = { - { "type", T_INT, offsetof(PyRemminaProtocolFeature, type), 0, NULL }, - { "id", T_INT, offsetof(PyRemminaProtocolFeature, id), 0, NULL }, - { "opt1", T_OBJECT, offsetof(PyRemminaProtocolFeature, opt1), 0, NULL }, - { "opt2", T_OBJECT, offsetof(PyRemminaProtocolFeature, opt2), 0, NULL }, - { "opt3", T_OBJECT, offsetof(PyRemminaProtocolFeature, opt3), 0, NULL }, - { NULL } -}; - -PyObject* python_protocol_feature_new(PyTypeObject* type, PyObject* kws, PyObject* args) -{ - TRACE_CALL(__func__); - - PyRemminaProtocolFeature* self; - self = (PyRemminaProtocolFeature*)type->tp_alloc(type, 0); - if (!self) - return NULL; - - self->id = 0; - self->type = 0; - self->opt1 = (PyGeneric*)Py_None; - self->opt1->raw = NULL; - self->opt1->type_hint = REMMINA_TYPEHINT_UNDEFINED; - self->opt2 = (PyGeneric*)Py_None; - self->opt2->raw = NULL; - self->opt2->type_hint = REMMINA_TYPEHINT_UNDEFINED; - self->opt3 = (PyGeneric*)Py_None; - self->opt3->raw = NULL; - self->opt3->type_hint = REMMINA_TYPEHINT_UNDEFINED; - - return (PyObject*)self; -} - -static int python_protocol_feature_init(PyRemminaProtocolFeature* self, PyObject* args, PyObject* kwargs) -{ - TRACE_CALL(__func__); - - static char* kwlist[] = { "type", "id", "opt1", "opt2", "opt3", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|llOOO", kwlist, &self->type, &self->id, &self->opt1, &self - ->opt2, &self->opt3)) - return -1; - - return 0; -} - -static PyTypeObject python_protocol_feature_type = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "remmina.ProtocolFeature", - .tp_doc = "Remmina Setting information", - .tp_basicsize = sizeof(PyRemminaProtocolFeature), - .tp_itemsize = 0, - .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_new = python_protocol_feature_new, - .tp_init = (initproc)python_protocol_feature_init, - .tp_members = python_protocol_feature_members -}; - -PyRemminaProtocolFeature* remmina_plugin_python_protocol_feature_new(void) -{ - PyRemminaProtocolFeature* feature = (PyRemminaProtocolFeature*)PyObject_New(PyRemminaProtocolFeature, &python_protocol_feature_type); - feature->id = 0; - feature->opt1 = remmina_plugin_python_generic_new(); - feature->opt1->raw = NULL; - feature->opt1->type_hint = REMMINA_TYPEHINT_UNDEFINED; - feature->opt2 = remmina_plugin_python_generic_new(); - feature->opt2->raw = NULL; - feature->opt2->type_hint = REMMINA_TYPEHINT_UNDEFINED; - feature->opt3 = remmina_plugin_python_generic_new(); - feature->opt3->raw = NULL; - feature->opt3->type_hint = REMMINA_TYPEHINT_UNDEFINED; - feature->type = 0; - Py_IncRef((PyObject*)feature); - return feature; -} - - -// -- Python Type -> Screenshot Data - -static PyMemberDef python_screenshot_data_members[] = { - { "buffer", T_OBJECT, offsetof(PyRemminaPluginScreenshotData, buffer), 0, NULL }, - { "width", T_INT, offsetof(PyRemminaPluginScreenshotData, width), 0, NULL }, - { "height", T_INT, offsetof(PyRemminaPluginScreenshotData, height), 0, NULL }, - { "bitsPerPixel", T_INT, offsetof(PyRemminaPluginScreenshotData, bitsPerPixel), 0, NULL }, - { "bytesPerPixel", T_INT, offsetof(PyRemminaPluginScreenshotData, bytesPerPixel), 0, NULL }, - { NULL } -}; - -PyObject* python_screenshot_data_new(PyTypeObject* type, PyObject* kws, PyObject* args) -{ - TRACE_CALL(__func__); - - PyRemminaPluginScreenshotData* self; - self = (PyRemminaPluginScreenshotData*)type->tp_alloc(type, 0); - if (!self) - return NULL; - - self->buffer = (PyByteArrayObject*)PyObject_New(PyByteArrayObject, &PyByteArray_Type); - self->height = 0; - self->width = 0; - self->bitsPerPixel = 0; - self->bytesPerPixel = 0; - - return (PyObject*)self; -} - -static int python_screenshot_data_init(PyRemminaPluginScreenshotData* self, PyObject* args, PyObject* kwargs) -{ - TRACE_CALL(__func__); - - g_printerr("Not to be initialized within Python!"); - return -1; -} - -static PyTypeObject python_screenshot_data_type = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "remmina.RemminaScreenshotData", - .tp_doc = "Remmina Screenshot Data", - .tp_basicsize = sizeof(PyRemminaPluginScreenshotData), - .tp_itemsize = 0, - .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_new = python_screenshot_data_new, - .tp_init = (initproc)python_screenshot_data_init, - .tp_members = python_screenshot_data_members -}; -PyRemminaPluginScreenshotData* remmina_plugin_python_screenshot_data_new(void) -{ - PyRemminaPluginScreenshotData* data = (PyRemminaPluginScreenshotData*)PyObject_New(PyRemminaPluginScreenshotData, &python_screenshot_data_type); - data->buffer = PyObject_New(PyByteArrayObject, &PyByteArray_Type); - Py_IncRef((PyObject*)data->buffer); - data->height = 0; - data->width = 0; - data->bitsPerPixel = 0; - data->bytesPerPixel = 0; - return data; -} - -static PyObject* remmina_plugin_python_generic_to_int(PyGeneric* self, PyObject* args); -static PyObject* remmina_plugin_python_generic_to_bool(PyGeneric* self, PyObject* args); -static PyObject* remmina_plugin_python_generic_to_string(PyGeneric* self, PyObject* args); - -static void remmina_plugin_python_generic_dealloc(PyObject* self) -{ - PyObject_Del(self); -} - -static PyMethodDef remmina_plugin_python_generic_methods[] = { - { "to_int", (PyCFunction)remmina_plugin_python_generic_to_int, METH_NOARGS, "" }, - { "to_bool", (PyCFunction)remmina_plugin_python_generic_to_bool, METH_NOARGS, "" }, - { "to_string", (PyCFunction)remmina_plugin_python_generic_to_string, METH_NOARGS, "" }, - { NULL } -}; - -static PyMemberDef remmina_plugin_python_generic_members[] = { - { "raw", T_OBJECT, offsetof(PyGeneric, raw), 0, "" }, - { NULL } -}; - -PyObject* remmina_plugin_python_generic_type_new(PyTypeObject* type, PyObject* kws, PyObject* args) -{ - TRACE_CALL(__func__); - - PyGeneric* self; - self = (PyGeneric*)type->tp_alloc(type, 0); - if (!self) - return NULL; - - self->raw = Py_None; - - return (PyObject*)self; -} - -static int remmina_plugin_python_generic_init(PyGeneric* self, PyObject* args, PyObject* kwargs) -{ - TRACE_CALL(__func__); - - static char* kwlist[] = { "raw", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &self->raw)) - return -1; - - return 0; -} - -static PyTypeObject python_generic_type = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "remmina.Generic", - .tp_doc = "", - .tp_basicsize = sizeof(PyGeneric), - .tp_itemsize = 0, - .tp_dealloc = remmina_plugin_python_generic_dealloc, - .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_new = remmina_plugin_python_generic_type_new, - .tp_init = (initproc)remmina_plugin_python_generic_init, - .tp_members = remmina_plugin_python_generic_members, - .tp_methods = remmina_plugin_python_generic_methods, -}; - -PyGeneric* remmina_plugin_python_generic_new(void) -{ - PyGeneric* generic = (PyGeneric*)PyObject_New(PyGeneric, &python_generic_type); - generic->raw = PyLong_FromLongLong(0LL); - Py_IncRef((PyObject*)generic); - return generic; -} - -static PyObject* remmina_plugin_python_generic_to_int(PyGeneric* self, PyObject* args) -{ - SELF_CHECK(); - - if (self->raw == NULL) - { - return Py_None; - } - else if (self->type_hint == REMMINA_TYPEHINT_SIGNED) - { - return PyLong_FromLongLong((long long)self->raw); - } - else if (self->type_hint == REMMINA_TYPEHINT_UNSIGNED) - { - return PyLong_FromUnsignedLongLong((unsigned long long)self->raw); - } - - return Py_None; -} -static PyObject* remmina_plugin_python_generic_to_bool(PyGeneric* self, PyObject* args) -{ - SELF_CHECK(); - - if (self->raw == NULL) - { - return Py_None; - } - else if (self->type_hint == REMMINA_TYPEHINT_BOOLEAN) - { - return PyBool_FromLong((long)self->raw); - } - - return Py_None; -} -static PyObject* remmina_plugin_python_generic_to_string(PyGeneric* self, PyObject* args) -{ - SELF_CHECK(); - - if (self->raw == NULL) - { - return Py_None; - } - else if (self->type_hint == REMMINA_TYPEHINT_STRING) - { - return PyUnicode_FromString((const char*)self->raw); - } - - return Py_None; -} - -/** - * Is called from the Python engine when it initializes the 'remmina' module. - * @details This function is only called by the Python engine! - */ -PyMODINIT_FUNC remmina_plugin_python_module_initialize(void) -{ - TRACE_CALL(__func__); - - if (PyType_Ready(&python_screenshot_data_type) < 0) - { - PyErr_Print(); - return NULL; - } - - if (PyType_Ready(&python_generic_type) < 0) - { - PyErr_Print(); - return NULL; - } - - if (PyType_Ready(&python_protocol_setting_type) < 0) - { - PyErr_Print(); - return NULL; - } - - if (PyType_Ready(&python_protocol_feature_type) < 0) - { - PyErr_Print(); - return NULL; - } - - remmina_plugin_python_protocol_widget_type_ready(); - remmina_plugin_python_remmina_init_types(); - - PyObject* module = PyModule_Create(&remmina_python_module_type); - if (!module) - { - PyErr_Print(); - return NULL; - } - - PyModule_AddIntConstant(module, "BUTTONS_CLOSE", (long)GTK_BUTTONS_CLOSE); - PyModule_AddIntConstant(module, "BUTTONS_NONE", (long)GTK_BUTTONS_NONE); - PyModule_AddIntConstant(module, "BUTTONS_OK", (long)GTK_BUTTONS_OK); - PyModule_AddIntConstant(module, "BUTTONS_CLOSE", (long)GTK_BUTTONS_CLOSE); - PyModule_AddIntConstant(module, "BUTTONS_CANCEL", (long)GTK_BUTTONS_CANCEL); - PyModule_AddIntConstant(module, "BUTTONS_YES_NO", (long)GTK_BUTTONS_YES_NO); - PyModule_AddIntConstant(module, "BUTTONS_OK_CANCEL", (long)GTK_BUTTONS_OK_CANCEL); - - PyModule_AddIntConstant(module, "MESSAGE_INFO", (long)GTK_MESSAGE_INFO); - PyModule_AddIntConstant(module, "MESSAGE_WARNING", (long)GTK_MESSAGE_WARNING); - PyModule_AddIntConstant(module, "MESSAGE_QUESTION", (long)GTK_MESSAGE_QUESTION); - PyModule_AddIntConstant(module, "MESSAGE_ERROR", (long)GTK_MESSAGE_ERROR); - PyModule_AddIntConstant(module, "MESSAGE_OTHER", (long)GTK_MESSAGE_OTHER); - - PyModule_AddIntConstant(module, "PROTOCOL_SETTING_TYPE_SERVER", (long)REMMINA_PROTOCOL_SETTING_TYPE_SERVER); - PyModule_AddIntConstant(module, "PROTOCOL_SETTING_TYPE_PASSWORD", (long)REMMINA_PROTOCOL_SETTING_TYPE_PASSWORD); - PyModule_AddIntConstant(module, "PROTOCOL_SETTING_TYPE_RESOLUTION", (long)REMMINA_PROTOCOL_SETTING_TYPE_RESOLUTION); - PyModule_AddIntConstant(module, "PROTOCOL_SETTING_TYPE_KEYMAP", (long)REMMINA_PROTOCOL_SETTING_TYPE_KEYMAP); - PyModule_AddIntConstant(module, "PROTOCOL_SETTING_TYPE_TEXT", (long)REMMINA_PROTOCOL_SETTING_TYPE_TEXT); - PyModule_AddIntConstant(module, "PROTOCOL_SETTING_TYPE_SELECT", (long)REMMINA_PROTOCOL_SETTING_TYPE_SELECT); - PyModule_AddIntConstant(module, "PROTOCOL_SETTING_TYPE_COMBO", (long)REMMINA_PROTOCOL_SETTING_TYPE_COMBO); - PyModule_AddIntConstant(module, "PROTOCOL_SETTING_TYPE_CHECK", (long)REMMINA_PROTOCOL_SETTING_TYPE_CHECK); - PyModule_AddIntConstant(module, "PROTOCOL_SETTING_TYPE_FILE", (long)REMMINA_PROTOCOL_SETTING_TYPE_FILE); - PyModule_AddIntConstant(module, "PROTOCOL_SETTING_TYPE_FOLDER", (long)REMMINA_PROTOCOL_SETTING_TYPE_FOLDER); - PyModule_AddIntConstant(module, "PROTOCOL_FEATURE_TYPE_MULTIMON", (long)REMMINA_PROTOCOL_FEATURE_TYPE_MULTIMON); - - PyModule_AddIntConstant(module, "PROTOCOL_FEATURE_TYPE_PREF", (long)REMMINA_PROTOCOL_FEATURE_TYPE_PREF); - PyModule_AddIntConstant(module, "PROTOCOL_FEATURE_TYPE_TOOL", (long)REMMINA_PROTOCOL_FEATURE_TYPE_TOOL); - PyModule_AddIntConstant(module, "PROTOCOL_FEATURE_TYPE_UNFOCUS", (long)REMMINA_PROTOCOL_FEATURE_TYPE_UNFOCUS); - PyModule_AddIntConstant(module, "PROTOCOL_FEATURE_TYPE_SCALE", (long)REMMINA_PROTOCOL_FEATURE_TYPE_SCALE); - PyModule_AddIntConstant(module, "PROTOCOL_FEATURE_TYPE_DYNRESUPDATE", (long)REMMINA_PROTOCOL_FEATURE_TYPE_DYNRESUPDATE); - PyModule_AddIntConstant(module, "PROTOCOL_FEATURE_TYPE_GTKSOCKET", (long)REMMINA_PROTOCOL_FEATURE_TYPE_GTKSOCKET); - - PyModule_AddIntConstant(module, "PROTOCOL_SSH_SETTING_NONE", (long)REMMINA_PROTOCOL_SSH_SETTING_NONE); - PyModule_AddIntConstant(module, "PROTOCOL_SSH_SETTING_TUNNEL", (long)REMMINA_PROTOCOL_SSH_SETTING_TUNNEL); - PyModule_AddIntConstant(module, "PROTOCOL_SSH_SETTING_SSH", (long)REMMINA_PROTOCOL_SSH_SETTING_SSH); - PyModule_AddIntConstant(module, "PROTOCOL_SSH_SETTING_REVERSE_TUNNEL", (long)REMMINA_PROTOCOL_SSH_SETTING_REVERSE_TUNNEL); - PyModule_AddIntConstant(module, "PROTOCOL_SSH_SETTING_SFTP", (long)REMMINA_PROTOCOL_SSH_SETTING_SFTP); - - PyModule_AddIntConstant(module, "PROTOCOL_FEATURE_PREF_RADIO", (long)REMMINA_PROTOCOL_FEATURE_PREF_RADIO); - PyModule_AddIntConstant(module, "PROTOCOL_FEATURE_PREF_CHECK", (long)REMMINA_PROTOCOL_FEATURE_PREF_CHECK); - - PyModule_AddIntConstant(module, "MESSAGE_PANEL_FLAG_USERNAME", REMMINA_MESSAGE_PANEL_FLAG_USERNAME); - PyModule_AddIntConstant(module, "MESSAGE_PANEL_FLAG_USERNAME_READONLY", REMMINA_MESSAGE_PANEL_FLAG_USERNAME_READONLY); - PyModule_AddIntConstant(module, "MESSAGE_PANEL_FLAG_DOMAIN", REMMINA_MESSAGE_PANEL_FLAG_DOMAIN); - PyModule_AddIntConstant(module, "MESSAGE_PANEL_FLAG_SAVEPASSWORD", REMMINA_MESSAGE_PANEL_FLAG_SAVEPASSWORD); - - if (PyModule_AddObject(module, "Setting", (PyObject*)&python_protocol_setting_type) < 0) - { - Py_DECREF(&python_protocol_setting_type); - Py_DECREF(module); - PyErr_Print(); - return NULL; - } - - Py_INCREF(&python_protocol_feature_type); - if (PyModule_AddObject(module, "Feature", (PyObject*)&python_protocol_feature_type) < 0) - { - Py_DECREF(&python_protocol_setting_type); - Py_DECREF(&python_protocol_feature_type); - Py_DECREF(module); - PyErr_Print(); - return NULL; - } - - return module; -} - -/** - * Initializes all globals and registers the 'remmina' module in the Python engine. - * @details This - */ -void remmina_plugin_python_module_init(void) -{ - TRACE_CALL(__func__); - - if (PyImport_AppendInittab("remmina", remmina_plugin_python_module_initialize)) - { - PyErr_Print(); - exit(1); - } - - remmina_plugin_python_entry_init(); - remmina_plugin_python_protocol_init(); - remmina_plugin_python_tool_init(); - remmina_plugin_python_pref_init(); - remmina_plugin_python_secret_init(); - remmina_plugin_python_file_init(); -} - -gboolean remmina_plugin_python_check_mandatory_member(PyObject* instance, const gchar* member) -{ - TRACE_CALL(__func__); - - if (PyObject_HasAttrString(instance, member)) - { - return TRUE; - } - - g_printerr("Missing mandatory member '%s' in Python plugin instance!\n", member); - return FALSE; -} - -static PyObject* remmina_register_plugin_wrapper(PyObject* self, PyObject* plugin_instance) -{ - TRACE_CALL(__func__); - - if (plugin_instance) - { - if (!remmina_plugin_python_check_mandatory_member(plugin_instance, "name") - || !remmina_plugin_python_check_mandatory_member(plugin_instance, "version")) - { - return NULL; - } - - /* Protocol plugin definition and features */ - const gchar* pluginType = PyUnicode_AsUTF8(PyObject_GetAttrString(plugin_instance, "type")); - - RemminaPlugin* remmina_plugin = NULL; - - PyPlugin* plugin = (PyPlugin*)remmina_plugin_python_malloc(sizeof(PyPlugin)); - plugin->instance = plugin_instance; - Py_INCREF(plugin_instance); - plugin->protocol_plugin = NULL; - plugin->entry_plugin = NULL; - plugin->file_plugin = NULL; - plugin->pref_plugin = NULL; - plugin->secret_plugin = NULL; - plugin->tool_plugin = NULL; - g_print("New Python plugin registered: %ld\n", PyObject_Hash(plugin_instance)); - - if (g_str_equal(pluginType, "protocol")) - { - remmina_plugin = remmina_plugin_python_create_protocol_plugin(plugin); - } - else if (g_str_equal(pluginType, "entry")) - { - remmina_plugin = remmina_plugin_python_create_entry_plugin(plugin); - } - else if (g_str_equal(pluginType, "file")) - { - remmina_plugin = remmina_plugin_python_create_file_plugin(plugin); - } - else if (g_str_equal(pluginType, "tool")) - { - remmina_plugin = remmina_plugin_python_create_tool_plugin(plugin); - } - else if (g_str_equal(pluginType, "pref")) - { - remmina_plugin = remmina_plugin_python_create_pref_plugin(plugin); - } - else if (g_str_equal(pluginType, "secret")) - { - remmina_plugin = remmina_plugin_python_create_secret_plugin(plugin); - } - else - { - g_printerr("Unknown plugin type: %s\n", pluginType); - } - - if (remmina_plugin) - { - if (remmina_plugin->type == REMMINA_PLUGIN_TYPE_PROTOCOL) - { - plugin->gp = remmina_plugin_python_protocol_widget_create(); - } - - remmina_plugin_manager_service.register_plugin((RemminaPlugin*)remmina_plugin); - } - } - - return Py_None; -} - -static PyObject* remmina_file_get_datadir_wrapper(PyObject* self, PyObject* plugin) -{ - TRACE_CALL(__func__); - - PyObject* result = Py_None; - const gchar* datadir = remmina_file_get_datadir(); - - if (datadir) - { - result = PyUnicode_FromFormat("%s", datadir); - } - - remmina_plugin_python_check_error(); - return result; -} - -static PyObject* remmina_file_new_wrapper(PyObject* self, PyObject* args, PyObject* kwargs) -{ - TRACE_CALL(__func__); - - RemminaFile* file = remmina_file_new(); - if (file) - { - return (PyObject*)remmina_plugin_python_remmina_file_to_python(file); - } - - remmina_plugin_python_check_error(); - return Py_None; -} - -static PyObject* remmina_pref_set_value_wrapper(PyObject* self, PyObject* args, PyObject* kwargs) -{ - TRACE_CALL(__func__); - - static char* kwlist[] = { "key", "value", NULL }; - gchar* key, * value; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss", kwlist, &key, &value)) - { - return Py_None; - } - - if (key) - { - remmina_pref_set_value(key, value); - } - - remmina_plugin_python_check_error(); - return Py_None; -} - -static PyObject* remmina_pref_get_value_wrapper(PyObject* self, PyObject* args, PyObject* kwargs) -{ - TRACE_CALL(__func__); - - static char* kwlist[] = { "key", NULL }; - gchar* key; - PyObject* result = Py_None; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &key)) - { - return Py_None; - } - - if (key) - { - const gchar* value = remmina_pref_get_value(key); - if (value) - { - result = PyUnicode_FromFormat("%s", result); - } - } - - remmina_plugin_python_check_error(); - return result; -} - -static PyObject* remmina_pref_get_scale_quality_wrapper(PyObject* self, PyObject* plugin) -{ - TRACE_CALL(__func__); - - PyObject* result = PyLong_FromLong(remmina_pref_get_scale_quality()); - remmina_plugin_python_check_error(); - return result; -} - -static PyObject* remmina_pref_get_sshtunnel_port_wrapper(PyObject* self, PyObject* plugin) -{ - TRACE_CALL(__func__); - - PyObject* result = PyLong_FromLong(remmina_pref_get_sshtunnel_port()); - remmina_plugin_python_check_error(); - return result; -} - -static PyObject* remmina_pref_get_ssh_loglevel_wrapper(PyObject* self, PyObject* plugin) -{ - TRACE_CALL(__func__); - - PyObject* result = PyLong_FromLong(remmina_pref_get_ssh_loglevel()); - remmina_plugin_python_check_error(); - return result; -} - -static PyObject* remmina_pref_get_ssh_parseconfig_wrapper(PyObject* self, PyObject* plugin) -{ - TRACE_CALL(__func__); - - PyObject* result = PyLong_FromLong(remmina_pref_get_ssh_parseconfig()); - remmina_plugin_python_check_error(); - return result; -} - -static PyObject* remmina_pref_keymap_get_keyval_wrapper(PyObject* self, PyObject* args, PyObject* kwargs) -{ - TRACE_CALL(__func__); - - static char* kwlist[] = { "keymap", "keyval", NULL }; - gchar* keymap; - guint keyval; - PyObject* result = Py_None; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sl", kwlist, &keymap, &keyval)) - { - return PyLong_FromLong(-1); - } - - if (keymap) - { - const guint value = remmina_pref_keymap_get_keyval(keymap, keyval); - result = PyLong_FromUnsignedLong(value); - } - - remmina_plugin_python_check_error(); - return result; -} - -static PyObject* remmina_plugin_python_log_print_wrapper(PyObject* self, PyObject* args) -{ - TRACE_CALL(__func__); - - gchar* text; - if (!PyArg_ParseTuple(args, "s", &text) || !text) - { - return Py_None; - } - - remmina_log_print(text); - return Py_None; -} - -static PyObject* remmina_plugin_python_debug_wrapper(PyObject* self, PyObject* args) -{ - TRACE_CALL(__func__); - - gchar* text; - if (!PyArg_ParseTuple(args, "s", &text) || !text) - { - return Py_None; - } - - remmina_plugin_manager_service._remmina_debug("python", "%s", text); - return Py_None; -} - -static PyObject* remmina_widget_pool_register_wrapper(PyObject* self, PyObject* args, PyObject* kwargs) -{ - TRACE_CALL(__func__); - - static char* kwlist[] = { "widget", NULL }; - PyObject* widget; - - if (PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &widget) && widget) - { - remmina_widget_pool_register(get_pywidget(widget)); - } - - return Py_None; -} - -static PyObject* rcw_open_from_file_full_wrapper(PyObject* self, PyObject* args, PyObject* kwargs) -{ - TRACE_CALL(__func__); - - static char* kwlist[] = { "remminafile", "data", "handler", NULL }; - PyObject* pyremminafile; - PyObject* data; - - if (PyArg_ParseTupleAndKeywords(args, kwargs, "OOO", kwlist, &pyremminafile, &data) && pyremminafile && data) - { - rcw_open_from_file_full((RemminaFile*)pyremminafile, NULL, (void*)data, NULL); - } - - return Py_None; -} - -static PyObject* remmina_public_get_server_port_wrapper(PyObject* self, PyObject* args, PyObject* kwargs) -{ - TRACE_CALL(__func__); - - static char* kwlist[] = { "server", "defaultport", "host", "port", NULL }; - gchar* server; - gint defaultport; - - if (PyArg_ParseTupleAndKeywords(args, kwargs, "slsl", kwlist, &server, &defaultport) && server) - { - gchar* host; - gint port; - remmina_public_get_server_port(server, defaultport, &host, &port); - - PyObject* result = PyList_New(2); - PyList_Append(result, PyUnicode_FromString(host)); - PyList_Append(result, PyLong_FromLong(port)); - return PyList_AsTuple(result); - } - - return Py_None; -} - -static PyObject* remmina_masterthread_exec_is_main_thread_wrapper(PyObject* self, PyObject* plugin) -{ - TRACE_CALL(__func__); - - return PyBool_FromLong(remmina_masterthread_exec_is_main_thread()); -} - -static PyObject* remmina_gtksocket_available_wrapper(PyObject* self, PyObject* plugin) -{ - TRACE_CALL(__func__); - - return PyBool_FromLong(remmina_gtksocket_available()); -} - -static PyObject* -remmina_protocol_widget_get_profile_remote_height_wrapper(PyObject* self, PyObject* args, PyObject* kwargs) -{ - TRACE_CALL(__func__); - - static char* kwlist[] = { "widget", NULL }; - PyPlugin* plugin; - - if (PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &plugin) && plugin && plugin->gp) - { - remmina_protocol_widget_get_profile_remote_height(plugin->gp->gp); - } - - return Py_None; -} - -static PyObject* -remmina_protocol_widget_get_profile_remote_width_wrapper(PyObject* self, PyObject* args, PyObject* kwargs) -{ - TRACE_CALL(__func__); - - static char* kwlist[] = { "widget", NULL }; - PyPlugin* plugin; - - if (PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &plugin) && plugin && plugin->gp) - { - remmina_protocol_widget_get_profile_remote_width(plugin->gp->gp); - } - - return Py_None; -} - -void remmina_plugin_python_to_protocol_setting(RemminaProtocolSetting* dest, PyObject* setting) -{ - TRACE_CALL(__func__); - - PyRemminaProtocolSetting* src = (PyRemminaProtocolSetting*)setting; - Py_INCREF(setting); - dest->name = src->name; - dest->label = src->label; - dest->compact = src->compact; - dest->type = src->settingType; - dest->validator = NULL; - dest->validator_data = NULL; - remmina_plugin_python_to_generic(src->opt1, &dest->opt1); - remmina_plugin_python_to_generic(src->opt2, &dest->opt2); -} - -void remmina_plugin_python_to_protocol_feature(RemminaProtocolFeature* dest, PyObject* feature) -{ - TRACE_CALL(__func__); - - PyRemminaProtocolFeature* src = (PyRemminaProtocolFeature*)feature; - Py_INCREF(feature); - dest->id = src->id; - dest->type = src->type; - dest->opt1 = src->opt1->raw; - dest->opt1_type_hint = src->opt1->type_hint; - dest->opt2 = src->opt2->raw; - dest->opt2_type_hint = src->opt2->type_hint; - dest->opt3 = src->opt3->raw; - dest->opt3_type_hint = src->opt3->type_hint; -} - -PyObject* remmina_plugin_python_show_dialog_wrapper(PyObject* self, PyObject* args, PyObject* kwargs) -{ - TRACE_CALL(__func__); - - static char* kwlist[] = { "type", "buttons", "message", NULL }; - GtkMessageType msgType; - GtkButtonsType btnType; - gchar* message; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "lls", kwlist, &msgType, &btnType, &message)) - { - return PyLong_FromLong(-1); - } - - remmina_main_show_dialog(msgType, btnType, message); - - return Py_None; -} - -PyObject* remmina_plugin_python_get_mainwindow_wrapper(PyObject* self, PyObject* args) -{ - TRACE_CALL(__func__); - - GtkWindow* result = remmina_main_get_window(); - - if (!result) - { - return Py_None; - } - - return (PyObject*)new_pywidget((GObject*)result); -} - -static PyObject* remmina_protocol_plugin_signal_connection_closed_wrapper(PyObject* self, PyObject* args) -{ - TRACE_CALL(__func__); - - PyObject* pygp = NULL; - if (!PyArg_ParseTuple(args, "O", &pygp) || !pygp) - { - g_printerr("Please provide the Remmina protocol widget instance!"); - return Py_None; - } - - remmina_plugin_manager_service.protocol_plugin_signal_connection_closed(((PyRemminaProtocolWidget*)pygp)->gp); - return Py_None; -} - -static PyObject* remmina_protocol_plugin_init_auth_wrapper(PyObject* module, PyObject* args, PyObject* kwds) -{ - TRACE_CALL(__func__); - - static gchar* keyword_list[] = { "widget", "flags", "title", "default_username", "default_password", - "default_domain", "password_prompt" }; - - PyRemminaProtocolWidget* self; - gint pflags = 0; - gchar* title, * default_username, * default_password, * default_domain, * password_prompt; - - if (PyArg_ParseTupleAndKeywords(args, kwds, "Oisssss", keyword_list, &self, &pflags, &title, &default_username, - &default_password, &default_domain, &password_prompt)) - { - if (pflags != 0 && !(pflags & REMMINA_MESSAGE_PANEL_FLAG_USERNAME) - && !(pflags & REMMINA_MESSAGE_PANEL_FLAG_USERNAME_READONLY) - && !(pflags & REMMINA_MESSAGE_PANEL_FLAG_DOMAIN) - && !(pflags & REMMINA_MESSAGE_PANEL_FLAG_SAVEPASSWORD)) - { - g_printerr("panel_auth(pflags, title, default_username, default_password, default_domain, password_prompt): " - "%d is not a known value for RemminaMessagePanelFlags!\n", pflags); - } - else - { - return Py_BuildValue("i", remmina_protocol_widget_panel_auth(self - ->gp, pflags, title, default_username, default_password, default_domain, password_prompt)); - } - } - else - { - g_printerr("panel_auth(pflags, title, default_username, default_password, default_domain, password_prompt): Error parsing arguments!\n"); - PyErr_Print(); - } - return Py_None; -} - -static PyObject* remmina_protocol_plugin_signal_connection_opened_wrapper(PyObject* self, PyObject* args) -{ - PyObject* pygp = NULL; - if (!PyArg_ParseTuple(args, "O", &pygp) || !pygp) - { - g_printerr("Please provide the Remmina protocol widget instance!"); - return Py_None; - } - - remmina_plugin_manager_service.protocol_plugin_signal_connection_opened(((PyRemminaProtocolWidget*)pygp)->gp); - return Py_None; -} diff --git a/src/remmina_plugin_python_remmina.h b/src/remmina_plugin_python_remmina.h deleted file mode 100644 index 25869d58a..000000000 --- a/src/remmina_plugin_python_remmina.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Remmina - The GTK+ Remote Desktop Client - * Copyright (C) 2014-2022 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. - */ - -/** - * @file remmina_plugin_python_remmina.h - * - * @brief Contains the implementation of the Python module 'remmina', provided to interface with the application from - * the Python plugin source. - * - * @detail In contrast to the wrapper functions that exist in the plugin specialisation files (e.g. - * remmina_plugin_python_protocol.c or remmina_plugin_python_entry.c), this file contains the API for the - * communication in the direction, from Python to Remmina. This means, if in the Python plugin a function - * is called, that is defined in Remmina, C code, at least in this file, is executed. - */ - -#pragma once - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// I N C L U D E S -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#include "remmina_plugin_python_protocol_widget.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// A P I -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -G_BEGIN_DECLS - -/** - * Initializes the 'remmina' module in the Python engine. - */ -void remmina_plugin_python_module_init(void); - -/** - * @brief Returns a pointer to the Python instance, mapped to the RemminaProtocolWidget or null if not found. - * - * @param gp The widget that is owned by the plugin that should be found. - * - * @details Remmina expects this callback function to be part of one plugin, which is the reason no instance information - * is explicitly passed. To bridge that, this function can be used to retrieve the very plugin instance owning - * the given RemminaProtocolWidget. - */ -PyPlugin* remmina_plugin_python_module_get_plugin(RemminaProtocolWidget* gp); - -/** - * @brief Converts the PyObject to RemminaProtocolSetting. - * - * @param dest A target for the converted value. - * @param setting The source value to convert. - */ -void remmina_plugin_python_to_protocol_setting(RemminaProtocolSetting* dest, PyObject* setting); - -/** - * @brief Converts the PyObject to RemminaProtocolFeature. - * - * @param dest A target for the converted value. - * @param setting The source value to convert. - */ -void remmina_plugin_python_to_protocol_feature(RemminaProtocolFeature* dest, PyObject* feature); - -G_END_DECLS diff --git a/src/remmina_plugin_python_remmina_file.c b/src/remmina_plugin_python_remmina_file.c deleted file mode 100644 index 1c417129a..000000000 --- a/src/remmina_plugin_python_remmina_file.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Remmina - The GTK+ Remote Desktop Client - * Copyright (C) 2016-2022 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. - */ - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// I N C L U D E S -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#include "remmina/remmina_trace_calls.h" -#include "remmina_file.h" -#include "remmina_plugin_python_common.h" -#include "remmina_plugin_python_remmina_file.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// D E C L A R A T I O N S -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -static PyObject* file_get_path(PyRemminaFile* self, PyObject* args); -static PyObject* file_set_setting(PyRemminaFile* self, PyObject* args, PyObject* kwds); -static PyObject* file_get_setting(PyRemminaFile* self, PyObject* args, PyObject* kwds); -static PyObject* file_get_secret(PyRemminaFile* self, PyObject* setting); -static PyObject* file_unsave_passwords(PyRemminaFile* self, PyObject* args); - -static void file_dealloc(PyObject* self) -{ - PyObject_Del(self); -} - -static PyMethodDef python_remmina_file_type_methods[] = { - { "get_path", (PyCFunction)file_get_path, METH_NOARGS, "" }, - { "set_setting", (PyCFunction)file_set_setting, METH_VARARGS | METH_KEYWORDS, "Set file setting" }, - { "get_setting", (PyCFunction)file_get_setting, METH_VARARGS | METH_KEYWORDS, "Get file setting" }, - { "get_secret", (PyCFunction)file_get_secret, METH_VARARGS, "Get secret file setting" }, - { "unsave_passwords", (PyCFunction)file_unsave_passwords, METH_NOARGS, "" }, - { NULL } -}; - -/** - * @brief The definition of the Python module 'remmina'. - */ -static PyTypeObject python_remmina_file_type = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "remmina.RemminaFile", - .tp_doc = "", - .tp_basicsize = sizeof(PyRemminaFile), - .tp_itemsize = 0, - .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_methods = python_remmina_file_type_methods, - .tp_dealloc = file_dealloc -}; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// A P I -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -void remmina_plugin_python_remmina_init_types(void) -{ - PyType_Ready(&python_remmina_file_type); -} - -PyRemminaFile* remmina_plugin_python_remmina_file_to_python(RemminaFile* file) -{ - TRACE_CALL(__func__); - - PyRemminaFile* result = PyObject_New(PyRemminaFile, &python_remmina_file_type); - result->file = file; - Py_INCREF(result); - return result; -} - -static PyObject* file_get_path(PyRemminaFile* self, PyObject* args) -{ - TRACE_CALL(__func__); - - return Py_BuildValue("s", remmina_file_get_filename(self->file)); -} - -static PyObject* file_set_setting(PyRemminaFile* self, PyObject* args, PyObject* kwds) -{ - TRACE_CALL(__func__); - - static char* keyword_list[] = { "key", "value", NULL }; - gchar* key; - PyObject* value; - - if (PyArg_ParseTupleAndKeywords(args, kwds, "s|O", keyword_list, &key, &value)) - { - if (PyUnicode_Check(value)) - { - remmina_file_set_string(self->file, key, PyUnicode_AsUTF8(value)); - } - else if (PyLong_Check(value)) - { - remmina_file_set_int(self->file, key, PyLong_AsLong(value)); - } - else - { - g_printerr("%s: Not a string or int value\n", PyUnicode_AsUTF8(PyObject_Str(value))); - } - return Py_None; - } - else - { - g_printerr("file.set_setting(key, value): Error parsing arguments!\n"); - PyErr_Print(); - return NULL; - } -} - -static PyObject* file_get_setting(PyRemminaFile* self, PyObject* args, PyObject* kwds) -{ - TRACE_CALL(__func__); - - static gchar* keyword_list[] = { "key", "default" }; - gchar* key; - PyObject* def; - - if (PyArg_ParseTupleAndKeywords(args, kwds, "sO", keyword_list, &key, &def)) - { - if (PyUnicode_Check(def)) - { - return Py_BuildValue("s", remmina_file_get_string(self->file, key)); - } - else if (PyBool_Check(def)) - { - return remmina_file_get_int(self->file, key, (gint)PyLong_AsLong(def)) ? Py_True : Py_False; - } - else if (PyLong_Check(def)) - { - return Py_BuildValue("i", remmina_file_get_int(self->file, key, (gint)PyLong_AsLong(def))); - } - else - { - g_printerr("%s: Not a string or int value\n", PyUnicode_AsUTF8(PyObject_Str(def))); - } - return def; - } - else - { - g_printerr("file.get_setting(key, default): Error parsing arguments!\n"); - PyErr_Print(); - return Py_None; - } -} - -static PyObject* file_get_secret(PyRemminaFile* self, PyObject* key) -{ - TRACE_CALL(__func__); - - if (key && PyUnicode_Check(key)) - { - return Py_BuildValue("s", remmina_file_get_secret(self->file, PyUnicode_AsUTF8(key))); - } - else - { - g_printerr("file.get_secret(key): Error parsing arguments!\n"); - PyErr_Print(); - return NULL; - } -} - -static PyObject* file_unsave_passwords(PyRemminaFile* self, PyObject* args) -{ - TRACE_CALL(__func__); - - if (self) - { - remmina_file_unsave_passwords(self->file); - return Py_None; - } - else - { - g_printerr("unsave_passwords(): self is null!\n"); - return NULL; - } -} diff --git a/src/remmina_plugin_python_remmina_file.h b/src/remmina_plugin_python_remmina_file.h deleted file mode 100644 index a2e7a53d3..000000000 --- a/src/remmina_plugin_python_remmina_file.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Remmina - The GTK+ Remote Desktop Client - * Copyright (C) 2016-2022 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. - */ - - -/** - * @file remmina_plugin_python_protocol.h - * - * @brief Contains the implementation of the Python type remmina.RemminaFile. - */ - -#pragma once - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// A P I -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * Wrapper for a Python object that contains a pointer to an instance of RemminaFile. - */ -typedef struct -{ - PyObject_HEAD - RemminaFile* file; -} PyRemminaFile; - -void remmina_plugin_python_remmina_init_types(void); - -/** - * Converts the instance of RemminaFile to a Python object that can be passed to the Python engine. - */ -PyRemminaFile* remmina_plugin_python_remmina_file_to_python(RemminaFile* file); diff --git a/src/remmina_plugin_python_secret.c b/src/remmina_plugin_python_secret.c deleted file mode 100644 index be659fdbb..000000000 --- a/src/remmina_plugin_python_secret.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Remmina - The GTK+ Remote Desktop Client - * Copyright (C) 2014-2021 Antenore Gatta, Giovanni Panozzo, Mathias Winterhalter (ToolsDevler) - * - * 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. - */ - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// I N L U C E S -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#include "remmina_plugin_python_common.h" -#include "remmina_plugin_python_secret.h" -#include "remmina_plugin_python_remmina_file.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// A P I -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -void remmina_plugin_python_secret_init(void) -{ - TRACE_CALL(__func__); -} - -gboolean remmina_plugin_python_secret_init_wrapper(RemminaSecretPlugin* instance) -{ - TRACE_CALL(__func__); - - PyPlugin* plugin = remmina_plugin_python_get_plugin(instance->name); - PyObject* result = CallPythonMethod(plugin->instance, "init", NULL); - return result == Py_None || result != Py_False; -} - -gboolean remmina_plugin_python_secret_is_service_available_wrapper(RemminaSecretPlugin* instance) -{ - TRACE_CALL(__func__); - - PyPlugin* plugin = remmina_plugin_python_get_plugin(instance->name); - PyObject* result = CallPythonMethod(plugin->instance, "is_service_available", NULL); - return result == Py_None || result != Py_False; -} - -void -remmina_plugin_python_secret_store_password_wrapper(RemminaSecretPlugin* instance, RemminaFile* file, const gchar* key, const gchar* password) -{ - TRACE_CALL(__func__); - - PyPlugin* plugin = remmina_plugin_python_get_plugin(instance->name); - CallPythonMethod(plugin - ->instance, "store_password", "Oss", (PyObject*)remmina_plugin_python_remmina_file_to_python(file), key, password); -} - -gchar* -remmina_plugin_python_secret_get_password_wrapper(RemminaSecretPlugin* instance, RemminaFile* file, const gchar* key) -{ - TRACE_CALL(__func__); - - PyPlugin* plugin = remmina_plugin_python_get_plugin(instance->name); - PyObject* result = CallPythonMethod(plugin - ->instance, "get_password", "Os", (PyObject*)remmina_plugin_python_remmina_file_to_python(file), key); - Py_ssize_t len = PyUnicode_GetLength(result); - if (len == 0) - { - return NULL; - } - - return remmina_plugin_python_copy_string_from_python(result, len); -} - -void -remmina_plugin_python_secret_delete_password_wrapper(RemminaSecretPlugin* instance, RemminaFile* file, const gchar* key) -{ - TRACE_CALL(__func__); - - PyPlugin* plugin = remmina_plugin_python_get_plugin(instance->name); - CallPythonMethod(plugin - ->instance, "delete_password", "Os", (PyObject*)remmina_plugin_python_remmina_file_to_python(file), key); -} - -RemminaPlugin* remmina_plugin_python_create_secret_plugin(PyPlugin* plugin) -{ - TRACE_CALL(__func__); - - PyObject* instance = plugin->instance; - - if (!remmina_plugin_python_check_attribute(instance, ATTR_NAME)) - { - return NULL; - } - - RemminaSecretPlugin* remmina_plugin = (RemminaSecretPlugin*)remmina_plugin_python_malloc(sizeof(RemminaSecretPlugin)); - - remmina_plugin->type = REMMINA_PLUGIN_TYPE_SECRET; - remmina_plugin->domain = GETTEXT_PACKAGE; - remmina_plugin->name = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_NAME)); - remmina_plugin->version = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_VERSION)); - remmina_plugin->description = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_DESCRIPTION)); - remmina_plugin->init_order = PyLong_AsLong(PyObject_GetAttrString(instance, ATTR_INIT_ORDER)); - - remmina_plugin->init = remmina_plugin_python_secret_init_wrapper; - remmina_plugin->is_service_available = remmina_plugin_python_secret_is_service_available_wrapper; - remmina_plugin->store_password = remmina_plugin_python_secret_store_password_wrapper; - remmina_plugin->get_password = remmina_plugin_python_secret_get_password_wrapper; - remmina_plugin->delete_password = remmina_plugin_python_secret_delete_password_wrapper; - - plugin->secret_plugin = remmina_plugin; - plugin->generic_plugin = (RemminaPlugin*)remmina_plugin; - - remmina_plugin_python_add_plugin(plugin); - - return (RemminaPlugin*)remmina_plugin; -}
\ No newline at end of file diff --git a/src/remmina_plugin_python_secret.h b/src/remmina_plugin_python_secret.h deleted file mode 100644 index c627d2a49..000000000 --- a/src/remmina_plugin_python_secret.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Remmina - The GTK+ Remote Desktop Client - * Copyright (C) 2014-2021 Antenore Gatta, Giovanni Panozzo, Mathias Winterhalter (ToolsDevler) - * - * 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. - */ - -/** - * @file remmina_plugin_python_entry.h - * - * @brief Contains the specialisation of RemminaPluginEntry plugins in Python. - */ - -#pragma once - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// I N L U C E S -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#include "remmina/plugin.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// A P I -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -G_BEGIN_DECLS - -/** - * Initializes the Python plugin specialisation for secret plugins. - */ -void remmina_plugin_python_secret_init(void); - -/** - * @brief Creates a new instance of the RemminaPluginSecret, initializes its members and references the wrapper - * functions. - * @param instance The instance of the Python plugin. - * @return Returns a new instance of the RemminaPlugin (must be freed!). - */ -RemminaPlugin* remmina_plugin_python_create_secret_plugin(PyPlugin* instance); - -G_END_DECLS diff --git a/src/remmina_plugin_python_tool.c b/src/remmina_plugin_python_tool.c deleted file mode 100644 index a951291f2..000000000 --- a/src/remmina_plugin_python_tool.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Remmina - The GTK+ Remote Desktop Client - * Copyright (C) 2014-2021 Antenore Gatta, Giovanni Panozzo, Mathias Winterhalter (ToolsDevler) - * - * 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. - */ - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// I N L U C E S -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#include "remmina_plugin_python_common.h" -#include "remmina_plugin_python_tool.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// A P I -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -void remmina_plugin_python_tool_init(void) -{ - TRACE_CALL(__func__); -} - -void remmina_plugin_python_tool_exec_func_wrapper(GtkMenuItem* self, RemminaToolPlugin* instance) -{ - TRACE_CALL(__func__); - - PyPlugin* plugin = remmina_plugin_python_get_plugin(instance->name); - CallPythonMethod(plugin->instance, "exec_func", NULL); -} - -RemminaPlugin* remmina_plugin_python_create_tool_plugin(PyPlugin* plugin) -{ - TRACE_CALL(__func__); - - PyObject* instance = plugin->instance; - - if (!remmina_plugin_python_check_attribute(instance, ATTR_NAME)) - { - return NULL; - } - - RemminaToolPlugin* remmina_plugin = (RemminaToolPlugin*)remmina_plugin_python_malloc(sizeof(RemminaToolPlugin)); - - remmina_plugin->type = REMMINA_PLUGIN_TYPE_TOOL; - remmina_plugin->domain = GETTEXT_PACKAGE; - remmina_plugin->name = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_NAME)); - remmina_plugin->version = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_VERSION)); - remmina_plugin->description = PyUnicode_AsUTF8(PyObject_GetAttrString(instance, ATTR_DESCRIPTION)); - remmina_plugin->exec_func = remmina_plugin_python_tool_exec_func_wrapper; - - plugin->tool_plugin = remmina_plugin; - plugin->generic_plugin = (RemminaPlugin*)remmina_plugin; - - remmina_plugin_python_add_plugin(plugin); - - return (RemminaPlugin*)remmina_plugin; -} diff --git a/src/remmina_plugin_python_tool.h b/src/remmina_plugin_python_tool.h deleted file mode 100644 index 08852bdc4..000000000 --- a/src/remmina_plugin_python_tool.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Remmina - The GTK+ Remote Desktop Client - * Copyright (C) 2014-2021 Antenore Gatta, Giovanni Panozzo, Mathias Winterhalter (ToolsDevler) - * - * 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. - */ - -/** - * @file remmina_plugin_python_entry.h - * - * @brief Contains the specialisation of RemminaPluginEntry plugins in Python. - */ - -#pragma once - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// I N L U C E S -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#include "remmina/plugin.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// A P I -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -G_BEGIN_DECLS - -/** - * Initializes the Python plugin specialisation for tool plugins. - */ -void remmina_plugin_python_tool_init(void); - -/** - * @brief Creates a new instance of the RemminaPluginTool, initializes its members and references the wrapper - * functions. - * @param instance The instance of the Python plugin. - * @return Returns a new instance of the RemminaPlugin (must be freed!). - */ -RemminaPlugin* remmina_plugin_python_create_tool_plugin(PyPlugin* instance); - -G_END_DECLS - diff --git a/src/remmina_protocol_widget.c b/src/remmina_protocol_widget.c index 9703d4cc5..5db892820 100644 --- a/src/remmina_protocol_widget.c +++ b/src/remmina_protocol_widget.c @@ -1372,6 +1372,11 @@ gint remmina_protocol_widget_get_profile_remote_height(RemminaProtocolWidget *gp return gp->priv->profile_remote_height; } +const gchar* remmina_protocol_widget_get_name(RemminaProtocolWidget *gp) +{ + TRACE_CALL(__func__); + return gp ? gp->plugin ? gp->plugin->name : NULL : NULL; +} gint remmina_protocol_widget_get_width(RemminaProtocolWidget *gp) { diff --git a/src/remmina_protocol_widget.h b/src/remmina_protocol_widget.h index e1a8f9987..c356df9c5 100644 --- a/src/remmina_protocol_widget.h +++ b/src/remmina_protocol_widget.h @@ -82,6 +82,7 @@ GtkWidget* remmina_protocol_widget_gtkviewport(RemminaProtocolWidget *gp); GtkWidget *remmina_protocol_widget_new(void); void remmina_protocol_widget_setup(RemminaProtocolWidget *gp, RemminaFile *remminafile, RemminaConnectionObject *cnnobj); +const gchar* remmina_protocol_widget_get_name(RemminaProtocolWidget *gp); gint remmina_protocol_widget_get_width(RemminaProtocolWidget *gp); void remmina_protocol_widget_set_width(RemminaProtocolWidget *gp, gint width); gint remmina_protocol_widget_get_height(RemminaProtocolWidget *gp); |