summaryrefslogtreecommitdiffstats
path: root/plugins/python_wrapper/python_wrapper_common.h
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/python_wrapper/python_wrapper_common.h')
-rw-r--r--plugins/python_wrapper/python_wrapper_common.h295
1 files changed, 295 insertions, 0 deletions
diff --git a/plugins/python_wrapper/python_wrapper_common.h b/plugins/python_wrapper/python_wrapper_common.h
new file mode 100644
index 0000000..8c7a167
--- /dev/null
+++ b/plugins/python_wrapper/python_wrapper_common.h
@@ -0,0 +1,295 @@
+/*
+ * Remmina - The GTK+ Remote Desktop Client
+ * Copyright (C) 2014-2023 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 python_wrapper_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 "common/remmina_plugin.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, ...) \
+ python_wrapper_last_result_set(PyObject_CallMethod(instance, name, params, ##__VA_ARGS__)); \
+ python_wrapper_log_method_call(instance, name); \
+ python_wrapper_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__); \
+ python_wrapper_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* python_wrapper_generic_new(void);
+
+/**
+ * Registers the given plugin if no other plugin with the same name has been already registered.
+ */
+void python_wrapper_add_plugin(PyPlugin* plugin);
+
+/**
+ * Sets the pointer to the plugin service of Remmina.
+ */
+void python_wrapper_set_service(RemminaPluginService* service);
+
+/**
+ * Gets the pointer to the plugin service of Remmina.
+ */
+RemminaPluginService* python_wrapper_get_service(void);
+
+/**
+ * Extracts data from a PyObject instance to a generic pointer and returns a type hint if it could be determined.
+ */
+RemminaTypeHint python_wrapper_to_generic(PyObject* field, gpointer* target);
+
+/**
+ * Gets the result of the last python method call.
+ */
+PyObject* python_wrapper_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* python_wrapper_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 python_wrapper_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 python_wrapper_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 python_wrapper_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 python_wrapper_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* python_wrapper_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* python_wrapper_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* python_wrapper_get_plugin(const gchar* name);
+
+/**
+ * @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* python_wrapper_get_plugin_by_protocol_widget(RemminaProtocolWidget* gp);
+
+/**
+ * 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