diff options
Diffstat (limited to 'libnm-core/nm-vpn-editor-plugin.c')
-rw-r--r-- | libnm-core/nm-vpn-editor-plugin.c | 284 |
1 files changed, 284 insertions, 0 deletions
diff --git a/libnm-core/nm-vpn-editor-plugin.c b/libnm-core/nm-vpn-editor-plugin.c new file mode 100644 index 0000000000..d5fa6d819b --- /dev/null +++ b/libnm-core/nm-vpn-editor-plugin.c @@ -0,0 +1,284 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2008 Novell, Inc. + * Copyright 2008 - 2010 Red Hat, Inc. + * Copyright 2015 Red Hat, Inc. + */ + +#include "config.h" + +#include "nm-vpn-editor-plugin.h" + +#include <gio/gio.h> +#include <glib/gi18n-lib.h> + +#include "nm-macros-internal.h" +#include "gsystem-local-alloc.h" +#include "nm-core-internal.h" + +static void nm_vpn_editor_plugin_default_init (NMVpnEditorPluginInterface *iface); + +G_DEFINE_INTERFACE (NMVpnEditorPlugin, nm_vpn_editor_plugin, G_TYPE_OBJECT) + +static void +nm_vpn_editor_plugin_default_init (NMVpnEditorPluginInterface *iface) +{ + /* Properties */ + + /** + * NMVpnEditorPlugin:name: + * + * Short display name of the VPN plugin. + */ + g_object_interface_install_property (iface, + g_param_spec_string (NM_VPN_EDITOR_PLUGIN_NAME, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMVpnEditorPlugin:description: + * + * Longer description of the VPN plugin. + */ + g_object_interface_install_property (iface, + g_param_spec_string (NM_VPN_EDITOR_PLUGIN_DESCRIPTION, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMVpnEditorPlugin:service: + * + * D-Bus service name of the plugin's VPN service. + */ + g_object_interface_install_property (iface, + g_param_spec_string (NM_VPN_EDITOR_PLUGIN_SERVICE, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); +} + +/*********************************************************************/ + +/** + * nm_vpn_editor_plugin_load_from_file: + * @plugin_filename: The path to the share library to load. + * Apply some common heuristics to find the library, such as + * appending "so" file ending. + * If the path is not an absolute path or no matching module + * can be found, lookup inside a directory defined at compile time. + * Due to this, @check_file might be called for two different paths. + * @check_name: if not-null, check that the loaded plugin has + * the given name. + * @check_service: if not-null, check that the loaded plugin advertises + * the given service. + * @check_owner: if non-negative, check whether the file is owned + * by UID @check_owner or by root. In this case also check that + * the file is not writable by anybody else. + * @check_file: optional callback to validate the file prior to + * loading the shared library. + * @user_data: user data for @check_file + * @error: on failure the error reason. + * + * Load the shared libary @plugin_filename and create a new + * #NMVpnEditorPlugin instace via the #NMVpnEditorPluginFactory + * function. + * + * Returns: (transfer-full): a new plugin instance or %NULL on error. + * + * Since: 1.2 + */ +NMVpnEditorPlugin * +nm_vpn_editor_plugin_load_from_file (const char *plugin_filename, + const char *check_name, + const char *check_service, + int check_owner, + NMUtilsCheckFilePredicate check_file, + gpointer user_data, + GError **error) +{ + GModule *module = NULL; + gs_free_error GError *local = NULL; + NMVpnEditorPluginFactory factory = NULL; + NMVpnEditorPlugin *editor_plugin = NULL; + + g_return_val_if_fail (plugin_filename && *plugin_filename, NULL); + + if (g_path_is_absolute (plugin_filename)) { + gs_free char *module_filename = NULL; + + module_filename = _nm_utils_check_module_file (plugin_filename, + check_owner, + check_file, + user_data, + &local); + if (module_filename) + module = g_module_open (module_filename, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); + } + + if (!module) { + if (local) { + g_propagate_error (error, local); + local = NULL; + } else { + g_set_error (error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("cannot load plugin %s"), plugin_filename); + } + return NULL; + } + g_clear_error (&local); + + if (g_module_symbol (module, "nm_vpn_editor_plugin_factory", (gpointer) &factory)) { + gs_free_error GError *factory_error = NULL; + gboolean success = FALSE; + + editor_plugin = factory (&factory_error); + + g_assert (!editor_plugin || G_IS_OBJECT (editor_plugin)); + + if (editor_plugin) { + gs_free char *plug_name = NULL, *plug_service = NULL; + + /* Validate plugin properties */ + + g_object_get (G_OBJECT (editor_plugin), + NM_VPN_EDITOR_PLUGIN_NAME, &plug_name, + NM_VPN_EDITOR_PLUGIN_SERVICE, &plug_service, + NULL); + + if (check_name && g_strcmp0 (plug_name, check_name) != 0) { + g_set_error (error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("cannot load VPN plugin in '%s': invalid plugin name"), + g_module_name (module)); + } else if ( check_service + && g_strcmp0 (plug_service, check_service) != 0) { + g_set_error (error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("cannot load VPN plugin in '%s': invalid service name"), + g_module_name (module)); + } else { + /* Success! */ + g_object_set_data_full (G_OBJECT (editor_plugin), "gmodule", module, + (GDestroyNotify) g_module_close); + success = TRUE; + } + } else { + if (factory_error) { + g_propagate_error (error, factory_error); + factory_error = NULL; + } else { + g_set_error (error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("unknown error initializing plugin %s"), plugin_filename); + } + } + + if (!success) { + g_module_close (module); + editor_plugin = NULL; + } + } else { + g_set_error (error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("failed to load nm_vpn_editor_plugin_factory() from %s (%s)"), + g_module_name (module), g_module_error ()); + g_module_close (module); + editor_plugin = NULL; + } + + return editor_plugin; +} + +/*********************************************************************/ + +/** + * nm_vpn_editor_plugin_get_editor: + * + * Returns: (transfer full): + */ +NMVpnEditor * +nm_vpn_editor_plugin_get_editor (NMVpnEditorPlugin *plugin, + NMConnection *connection, + GError **error) +{ + g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), NULL); + + return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_editor (plugin, connection, error); +} + +NMVpnEditorPluginCapability +nm_vpn_editor_plugin_get_capabilities (NMVpnEditorPlugin *plugin) +{ + g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), 0); + + return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_capabilities (plugin); +} + +/** + * nm_vpn_editor_plugin_import: + * + * Returns: (transfer full): + */ +NMConnection * +nm_vpn_editor_plugin_import (NMVpnEditorPlugin *plugin, + const char *path, + GError **error) +{ + g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), NULL); + + if (nm_vpn_editor_plugin_get_capabilities (plugin) & NM_VPN_EDITOR_PLUGIN_CAPABILITY_IMPORT) { + g_return_val_if_fail (NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->import_from_file != NULL, NULL); + return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->import_from_file (plugin, path, error); + } + return NULL; +} + +gboolean +nm_vpn_editor_plugin_export (NMVpnEditorPlugin *plugin, + const char *path, + NMConnection *connection, + GError **error) +{ + g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), FALSE); + + if (nm_vpn_editor_plugin_get_capabilities (plugin) & NM_VPN_EDITOR_PLUGIN_CAPABILITY_EXPORT) { + g_return_val_if_fail (NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->export_to_file != NULL, FALSE); + return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->export_to_file (plugin, path, connection, error); + } + return FALSE; +} + +char * +nm_vpn_editor_plugin_get_suggested_filename (NMVpnEditorPlugin *plugin, + NMConnection *connection) +{ + g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), NULL); + + if (NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_suggested_filename) + return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_suggested_filename (plugin, connection); + return NULL; +} + |