summaryrefslogtreecommitdiff
path: root/native/plugin
diff options
context:
space:
mode:
authorAndrew John Hughes <gnu_andrew@member.fsf.org>2006-06-11 18:23:15 +0000
committerAndrew John Hughes <gnu_andrew@member.fsf.org>2006-06-11 18:23:15 +0000
commit35d18ccf396a6cfdcbe5bbdf38df7d01852250bc (patch)
tree562e6d161a8957db8a46900b46f661c5e52e1a34 /native/plugin
parentc5877847749d21bdf84e33929ffa52a56e5c6ca0 (diff)
downloadclasspath-35d18ccf396a6cfdcbe5bbdf38df7d01852250bc.tar.gz
2006-06-11 Andrew John Hughes <gnu_andrew@member.fsf.org>
* Merge of HEAD-->generics between 2006/05/29 and 2006/06/11.
Diffstat (limited to 'native/plugin')
-rw-r--r--native/plugin/Makefile.am14
-rw-r--r--native/plugin/gcjwebplugin.cc575
2 files changed, 479 insertions, 110 deletions
diff --git a/native/plugin/Makefile.am b/native/plugin/Makefile.am
index 7358381eb..e1331fe45 100644
--- a/native/plugin/Makefile.am
+++ b/native/plugin/Makefile.am
@@ -4,15 +4,15 @@ libgcjwebplugin_la_SOURCES = gcjwebplugin.cc
libgcjwebplugin_la_CXXFLAGS = \
-Wall -DAPPLETVIEWER_EXECUTABLE="\"$(bindir)/appletviewer\"" \
- $(MOZILLA_CFLAGS) $(GLIB_CFLAGS)
+ $(MOZILLA_CFLAGS) $(GLIB_CFLAGS) $(GTK_CFLAGS)
libgcjwebplugin_la_LDFLAGS = -avoid-version \
- $(GLIB_LIBS) \
+ $(GLIB_LIBS) $(GTK_LIBS) \
-lstdc++
-install-libLTLIBRARIES: $(lib_LTLIBRARIES)
- $(INSTALL) -d -m0755 $(DESTDIR)@PLUGIN_DIR@
- $(INSTALL) .libs/libgcjwebplugin.so $(DESTDIR)@PLUGIN_DIR@
+install-plugin: $(lib_LTLIBRARIES)
+ $(INSTALL) -d -m0755 $(DESTDIR)$(PLUGIN_DIR)
+ $(INSTALL) .libs/libgcjwebplugin.so $(DESTDIR)$(PLUGIN_DIR)
-uninstall-libLTLIBRARIES:
- rm -f $(DESTDIR)@PLUGIN_DIR@/libgcjwebplugin.so
+uninstall-plugin:
+ rm -f $(DESTDIR)$(PLUGIN_DIR)/libgcjwebplugin.so
diff --git a/native/plugin/gcjwebplugin.cc b/native/plugin/gcjwebplugin.cc
index bbb9809be..ad65c7ef1 100644
--- a/native/plugin/gcjwebplugin.cc
+++ b/native/plugin/gcjwebplugin.cc
@@ -49,6 +49,10 @@ exception statement from your version. */
// GLib includes.
#include <glib.h>
+#include <glib/gstdio.h>
+
+// GTK includes.
+#include <gtk/gtk.h>
// gcjwebplugin includes.
#include "config.h"
@@ -75,6 +79,10 @@ exception statement from your version. */
g_printerr ("%s:%d: thread %p: Error: %s: %s\n", __FILE__, __LINE__, \
g_thread_self (), first, second)
+#define PLUGIN_ERROR_THREE(first, second, third) \
+ g_printerr ("%s:%d: thread %p: Error: %s: %s: %s\n", __FILE__, \
+ __LINE__, g_thread_self (), first, second, third)
+
// Plugin information passed to about:plugins.
#define PLUGIN_NAME "GCJ Web Browser Plugin"
#define PLUGIN_DESC "The " PLUGIN_NAME " executes Java applets."
@@ -113,8 +121,25 @@ exception statement from your version. */
#define PLUGIN_FILE_EXTS "class,jar,zip"
#define PLUGIN_MIME_COUNT 1
-// Directory in which named pipes are created.
-#define PIPE_DIRECTORY "/tmp"
+// Security dialog messages.
+#define RESPONSE_TRUST_APPLET "Trust Applet"
+#define RESPONSE_TRUST_APPLET_ADD_TO_LIST "Trust Applet and Add to Whitelist"
+#define SECURITY_WARNING \
+ "%s wants to load an applet.\n" \
+ "GNU Classpath's security implementation is not complete.\n" \
+ "HOSTILE APPLETS WILL STEAL AND/OR DESTROY YOUR DATA!\n"
+#define SECURITY_DESCRIPTION \
+ "Click \"Cancel\" if you do not trust the source of this applet.\n" \
+ "Click \"Trust Applet\" to load and run this applet now.\n" \
+ "Click \"Trust Applet and Add To Whitelist\" to always load" \
+ " and run this applet from now on, without asking.\n" \
+ "The whitelist is a list of the URLs from which you trust" \
+ " applets.\n" \
+ "Your whitelist file is \" %s \"."
+#define FAILURE_MESSAGE \
+ "This page wants to load an applet.\n" \
+ "The appletviewer is missing or not installed properly in \"" \
+ APPLETVIEWER_EXECUTABLE "\"."
// Documentbase retrieval required definition.
static NS_DEFINE_IID (kIPluginTagInfo2IID, NS_IPLUGINTAGINFO2_IID);
@@ -122,6 +147,16 @@ static NS_DEFINE_IID (kIPluginTagInfo2IID, NS_IPLUGINTAGINFO2_IID);
// Browser function table.
static NPNetscapeFuncs browserFunctions;
+// Data directory for plugin.
+static gchar* data_directory;
+
+// Whitelist filename
+static gchar* whitelist_filename;
+
+// Keeps track of initialization. NP_Initialize should only be
+// called once.
+gboolean initialized = false;
+
// GCJPluginData stores all the data associated with a single plugin
// instance. A separate plugin instance is created for each <APPLET>
// tag. For now, each plugin instance spawns its own applet viewer
@@ -173,6 +208,12 @@ typedef union
static void plugin_data_new (GCJPluginData** data);
// Documentbase retrieval.
static gchar* plugin_get_documentbase (NPP instance);
+// plugin failure handling.
+static bool plugin_failed ();
+// Whitelist handling.
+static bool plugin_user_trusts_documentbase (char* documentbase);
+static bool plugin_ask_user_about_documentbase (char* documentbase);
+static void plugin_add_documentbase_to_whitelist (char* documentbase);
// Callback used to monitor input pipe status.
static gboolean plugin_in_pipe_callback (GIOChannel* source,
GIOCondition condition,
@@ -181,7 +222,7 @@ static gboolean plugin_in_pipe_callback (GIOChannel* source,
static gboolean plugin_out_pipe_callback (GIOChannel* source,
GIOCondition condition,
gpointer plugin_data);
-static void plugin_start_appletviewer (GCJPluginData* data);
+static NPError plugin_start_appletviewer (GCJPluginData* data);
static gchar* plugin_create_applet_tag (int16 argc, char* argn[],
char* argv[]);
static void plugin_send_message_to_appletviewer (GCJPluginData* data,
@@ -195,6 +236,11 @@ static void plugin_data_destroy (GCJPluginData** data);
static GMutex* plugin_instance_mutex = NULL;
// A counter used to create uniquely named pipes.
static gulong plugin_instance_counter = 0;
+// The user's documentbase whitelist.
+static GIOChannel* whitelist_file = NULL;
+// A global variable for reporting GLib errors. This must be free'd
+// and set to NULL after each use.
+static GError* channel_error = NULL;
// Functions prefixed by GCJ_ are instance functions. They are called
// by the browser and operate on instances of GCJPluginData.
@@ -224,7 +270,7 @@ GCJ_New (NPMIMEType pluginType, NPP instance, uint16 mode,
NPError np_error = NPERR_NO_ERROR;
GCJPluginData* data = NULL;
- GError* channel_error = NULL;
+
gchar* documentbase = NULL;
gchar* read_message = NULL;
gchar* applet_tag = NULL;
@@ -278,13 +324,19 @@ GCJ_New (NPMIMEType pluginType, NPP instance, uint16 mode,
goto cleanup_appletviewer_mutex;
}
+ if (!plugin_user_trusts_documentbase (documentbase))
+ {
+ PLUGIN_ERROR ("User does not trust applet.");
+ np_error = NPERR_GENERIC_ERROR;
+ goto cleanup_appletviewer_mutex;
+ }
+
// Create appletviewer-to-plugin pipe which we refer to as the input
// pipe.
// data->in_pipe_name
- data->in_pipe_name = g_strdup_printf (PIPE_DIRECTORY
- "/gcj-%s-appletviewer-to-plugin",
- data->instance_string);
+ data->in_pipe_name = g_strdup_printf ("%s/gcj-%s-appletviewer-to-plugin",
+ data_directory, data->instance_string);
if (!data->in_pipe_name)
{
PLUGIN_ERROR ("Failed to create input pipe name.");
@@ -305,9 +357,8 @@ GCJ_New (NPMIMEType pluginType, NPP instance, uint16 mode,
// output pipe.
// data->out_pipe_name
- data->out_pipe_name = g_strdup_printf (PIPE_DIRECTORY
- "/gcj-%s-plugin-to-appletviewer",
- data->instance_string);
+ data->out_pipe_name = g_strdup_printf ("%s/gcj-%s-plugin-to-appletviewer",
+ data_directory, data->instance_string);
if (!data->out_pipe_name)
{
@@ -332,9 +383,17 @@ GCJ_New (NPMIMEType pluginType, NPP instance, uint16 mode,
// appletviewer, create the IO channels and install the channel
// watch callbacks.
g_mutex_lock (data->appletviewer_mutex);
-
- plugin_start_appletviewer (data);
-
+
+ np_error = plugin_start_appletviewer (data);
+
+ // If the appletviewer is not installed, then a dialog box will
+ // show up and the plugin will be killed.
+ if (np_error != NPERR_NO_ERROR)
+ {
+ if (plugin_failed ())
+ goto cleanup_applet_failure;
+ }
+
// Create plugin-to-appletviewer channel. The default encoding for
// the file is UTF-8.
// data->out_to_appletviewer
@@ -342,16 +401,19 @@ GCJ_New (NPMIMEType pluginType, NPP instance, uint16 mode,
"w", &channel_error);
if (!data->out_to_appletviewer)
{
- PLUGIN_ERROR_TWO ("Failed to create output channel",
- channel_error->message);
+ if (channel_error)
+ {
+ PLUGIN_ERROR_TWO ("Failed to create output channel",
+ channel_error->message);
+ g_error_free (channel_error);
+ channel_error = NULL;
+ }
+ else
+ PLUGIN_ERROR ("Failed to create output channel");
+
np_error = NPERR_GENERIC_ERROR;
goto cleanup_out_to_appletviewer;
}
- if (channel_error)
- {
- g_error_free (channel_error);
- channel_error = NULL;
- }
// Watch for hangup and error signals on the output pipe.
data->out_watch_source =
@@ -366,16 +428,19 @@ GCJ_New (NPMIMEType pluginType, NPP instance, uint16 mode,
"r", &channel_error);
if (!data->in_from_appletviewer)
{
- PLUGIN_ERROR_TWO ("Failed to create input channel",
- channel_error->message);
+ if (channel_error)
+ {
+ PLUGIN_ERROR_TWO ("Failed to create input channel",
+ channel_error->message);
+ g_error_free (channel_error);
+ channel_error = NULL;
+ }
+ else
+ PLUGIN_ERROR ("Failed to create input channel");
+
np_error = NPERR_GENERIC_ERROR;
goto cleanup_in_from_appletviewer;
}
- if (channel_error)
- {
- g_error_free (channel_error);
- channel_error = NULL;
- }
// Watch for hangup and error signals on the input pipe.
data->in_watch_source =
@@ -390,16 +455,19 @@ GCJ_New (NPMIMEType pluginType, NPP instance, uint16 mode,
&channel_error)
!= G_IO_STATUS_NORMAL)
{
- PLUGIN_ERROR_TWO ("Receiving confirmation from appletviewer failed",
- channel_error->message);
+ if (channel_error)
+ {
+ PLUGIN_ERROR_TWO ("Receiving confirmation from appletviewer failed",
+ channel_error->message);
+ g_error_free (channel_error);
+ channel_error = NULL;
+ }
+ else
+ PLUGIN_ERROR ("Receiving confirmation from appletviewer failed");
+
np_error = NPERR_GENERIC_ERROR;
goto cleanup_in_watch_source;
}
- if (channel_error)
- {
- g_error_free (channel_error);
- channel_error = NULL;
- }
PLUGIN_DEBUG ("GCJ_New: got confirmation that appletviewer is running.");
data->appletviewer_alive = TRUE;
@@ -448,7 +516,8 @@ GCJ_New (NPMIMEType pluginType, NPP instance, uint16 mode,
// cleanup_out_pipe:
// Delete output pipe.
unlink (data->out_pipe_name);
-
+
+ cleanup_applet_failure:
cleanup_out_pipe_name:
g_free (data->out_pipe_name);
data->out_pipe_name = NULL;
@@ -480,7 +549,6 @@ GCJ_New (NPMIMEType pluginType, NPP instance, uint16 mode,
instance->pdata = NULL;
cleanup_done:
-
g_free (tag_message);
tag_message = NULL;
g_free (applet_tag);
@@ -602,6 +670,7 @@ GCJ_SetWindow (NPP instance, NPWindow* window)
window->width);
plugin_send_message_to_appletviewer (data, width_message);
g_free (width_message);
+ width_message = NULL;
// Store the new width.
data->window_width = window->width;
@@ -619,6 +688,7 @@ GCJ_SetWindow (NPP instance, NPWindow* window)
window->height);
plugin_send_message_to_appletviewer (data, height_message);
g_free (height_message);
+ height_message = NULL;
// Store the new height.
data->window_height = window->height;
@@ -651,6 +721,7 @@ GCJ_SetWindow (NPP instance, NPWindow* window)
(gulong) window->window);
plugin_send_message_to_appletviewer (data, window_message);
g_free (window_message);
+ window_message = NULL;
g_mutex_unlock (data->appletviewer_mutex);
@@ -833,6 +904,201 @@ plugin_get_documentbase (NPP instance)
return documentbase_copy;
}
+// This function shows a error message if the appletviewer has
+// not been installed. It returns true, if the user presses the
+// ok button.
+static bool
+plugin_failed ()
+{
+ GtkWidget* dialog = NULL;
+ GtkWidget* ok_button = NULL;
+
+ dialog = gtk_message_dialog_new (NULL,
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_NONE,
+ FAILURE_MESSAGE);
+ ok_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ GTK_STOCK_OK,
+ GTK_RESPONSE_OK);
+ gtk_widget_show_all (dialog);
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
+ {
+ gtk_widget_destroy (dialog);
+ return true;
+ }
+ return false;
+}
+
+// plugin_user_trusts_documentbase returns true if the given
+// documentbase is in the documentbase whitelist. Otherwise it asks
+// the user if he trusts the given documentbase by calling
+// plugin_ask_user_about_documentbase.
+static bool
+plugin_user_trusts_documentbase (char* documentbase)
+{
+ bool applet_in_whitelist = false;
+
+ // Check if documentbase is in whitelist.
+ while (true)
+ {
+ gchar* whitelist_entry = NULL;
+ gchar* newline_documentbase = NULL;
+
+ // If reading fails, break out of this loop with
+ // applet_in_whitelist still set to false.
+ if (g_io_channel_read_line (whitelist_file, &whitelist_entry,
+ NULL, NULL, &channel_error)
+ != G_IO_STATUS_NORMAL)
+ {
+ if (channel_error)
+ {
+ PLUGIN_ERROR_TWO ("Failed to read line from whitelist file",
+ channel_error->message);
+ g_error_free (channel_error);
+ channel_error = NULL;
+ }
+ else
+ PLUGIN_ERROR ("Failed to open whitelist file.");
+ g_free (whitelist_entry);
+ whitelist_entry = NULL;
+ break;
+ }
+
+ newline_documentbase = g_strdup_printf ("%s\n", documentbase);
+ if (!strcmp (newline_documentbase, whitelist_entry))
+ {
+ applet_in_whitelist = true;
+ g_free (newline_documentbase);
+ newline_documentbase = NULL;
+ g_free (whitelist_entry);
+ whitelist_entry = NULL;
+ break;
+ }
+ g_free (whitelist_entry);
+ whitelist_entry = NULL;
+ g_free (newline_documentbase);
+ newline_documentbase = NULL;
+ }
+
+ return applet_in_whitelist ? true
+ : plugin_ask_user_about_documentbase (documentbase);
+}
+
+// plugin_add_documentbase_to_whitelist adds the given documentbase to
+// the user's documentbase whitelist.
+static void
+plugin_add_documentbase_to_whitelist (char* documentbase)
+{
+ gsize bytes_written = 0;
+ char* newline_documentbase = NULL;
+ GIOStatus status = G_IO_STATUS_NORMAL;
+
+ newline_documentbase = g_strdup_printf ("%s\n", documentbase);
+ status = g_io_channel_write_chars (whitelist_file,
+ newline_documentbase, -1, &bytes_written,
+ &channel_error);
+ g_free (newline_documentbase);
+ newline_documentbase = NULL;
+
+ if (status != G_IO_STATUS_NORMAL)
+ {
+ if (channel_error)
+ {
+ PLUGIN_ERROR_TWO ("Error writing to whitelist file",
+ channel_error->message);
+ g_error_free (channel_error);
+ channel_error = NULL;
+ }
+ else
+ PLUGIN_ERROR ("Error writing to whitelist file.");
+ }
+
+ if (g_io_channel_flush (whitelist_file, &channel_error)
+ != G_IO_STATUS_NORMAL)
+ {
+ if (channel_error)
+ {
+ PLUGIN_ERROR_TWO ("Failed to write whitelist file",
+ channel_error->message);
+ g_error_free (channel_error);
+ channel_error = NULL;
+ }
+ else
+ PLUGIN_ERROR ("Failed to write whitelist file.");
+ }
+
+ if (g_io_channel_shutdown (whitelist_file, TRUE, &channel_error)
+ != G_IO_STATUS_NORMAL)
+ {
+ if (channel_error)
+ {
+ PLUGIN_ERROR_TWO ("Failed to close whitelist file",
+ channel_error->message);
+ g_error_free (channel_error);
+ channel_error = NULL;
+ }
+ else
+ PLUGIN_ERROR ("Failed to close whitelist file.");
+ }
+}
+
+// plugin_ask_user_about_documentbase puts up a dialog box that asks if the
+// user trusts applets from this documentbase. The user has three
+// options: "Cancel", "Trust Applet" and "Trust Applet and Add to
+// Whitelist". If the user selects Cancel (the default) then a
+// generic error code is returned from GCJ_New, telling the browser
+// that the applet failed to load. If the user selects "Trust Applet"
+// then plugin loading proceeds. If the user selects "Trust Applet
+// and Add to Whitelist" then this documentbase is added to the user's
+// applet whitelist and plugin loading proceeds.
+static bool
+plugin_ask_user_about_documentbase (char* documentbase)
+{
+ GtkWidget* dialog = NULL;
+ GtkWidget* ok_button = NULL;
+ GtkWidget* cancel_button = NULL;
+ GtkWidget* whitelist_button = NULL;
+ gint dialog_response = GTK_RESPONSE_NONE;
+
+ dialog = gtk_message_dialog_new (NULL,
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_NONE,
+ SECURITY_WARNING,
+ documentbase);
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ SECURITY_DESCRIPTION, whitelist_filename);
+
+ cancel_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL);
+ ok_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ RESPONSE_TRUST_APPLET,
+ GTK_RESPONSE_OK);
+ whitelist_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ RESPONSE_TRUST_APPLET_ADD_TO_LIST,
+ GTK_RESPONSE_APPLY);
+ gtk_widget_grab_focus (cancel_button);
+
+ gtk_widget_show_all (dialog);
+ dialog_response = gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ if (dialog_response == GTK_RESPONSE_CANCEL)
+ {
+ // The user does not trust this documentbase.
+ return false;
+ }
+ else if (dialog_response == GTK_RESPONSE_APPLY)
+ {
+ // The user wants this documentbase added to his documentbase
+ // whitelist.
+ plugin_add_documentbase_to_whitelist (documentbase);
+ }
+ // The user trusts this documentbase.
+ return true;
+}
+
// plugin_in_pipe_callback is called when data is available on the
// input pipe, or when the appletviewer crashes or is killed. It may
// be called after data has been destroyed in which case it simply
@@ -858,7 +1124,6 @@ plugin_in_pipe_callback (GIOChannel* source,
if (condition & G_IO_IN)
{
- GError* channel_error = NULL;
gchar* message = NULL;
if (g_io_channel_read_line (data->in_from_appletviewer,
@@ -866,8 +1131,15 @@ plugin_in_pipe_callback (GIOChannel* source,
&channel_error)
!= G_IO_STATUS_NORMAL)
{
- PLUGIN_ERROR_TWO ("Failed to read line from input channel",
- channel_error->message);
+ if (channel_error)
+ {
+ PLUGIN_ERROR_TWO ("Failed to read line from input channel",
+ channel_error->message);
+ g_error_free (channel_error);
+ channel_error = NULL;
+ }
+ else
+ PLUGIN_ERROR ("Failed to read line from input channel");
}
else
{
@@ -899,12 +1171,6 @@ plugin_in_pipe_callback (GIOChannel* source,
g_print (" PIPE: plugin read %s\n", message);
}
- if (channel_error)
- {
- g_error_free (channel_error);
- channel_error = NULL;
- }
-
g_free (message);
message = NULL;
@@ -958,14 +1224,14 @@ plugin_out_pipe_callback (GIOChannel* source,
return FALSE;
}
-static void
+static NPError
plugin_start_appletviewer (GCJPluginData* data)
{
PLUGIN_DEBUG ("plugin_start_appletviewer");
-
+ NPError error = NPERR_NO_ERROR;
+
if (!data->appletviewer_alive)
{
- GError* spawn_error = NULL;
gchar* command_line[3] = { NULL, NULL, NULL };
command_line[0] = g_strdup (APPLETVIEWER_EXECUTABLE);
@@ -977,25 +1243,32 @@ plugin_start_appletviewer (GCJPluginData* data)
command_line[2] = NULL;
if (!g_spawn_async (NULL, command_line, NULL, (GSpawnFlags) 0,
- NULL, NULL, NULL, &spawn_error))
+ NULL, NULL, NULL, &channel_error))
{
- PLUGIN_ERROR_TWO ("Failed to spawn applet viewer",
- spawn_error->message);
+ if (channel_error)
+ {
+ PLUGIN_ERROR_TWO ("Failed to spawn applet viewer",
+ channel_error->message);
+ g_error_free (channel_error);
+ channel_error = NULL;
+ }
+ else
+ PLUGIN_ERROR ("Failed to spawn applet viewer");
+ error = NPERR_GENERIC_ERROR;
goto cleanup;
}
cleanup:
g_free (command_line[0]);
+ command_line[0] = NULL;
g_free (command_line[1]);
+ command_line[1] = NULL;
g_free (command_line[2]);
- if (spawn_error)
- {
- g_error_free (spawn_error);
- spawn_error = NULL;
- }
+ command_line[2] = NULL;
}
PLUGIN_DEBUG ("plugin_start_appletviewer return");
+ return error;
}
// Build up the applet tag string that we'll send to the applet
@@ -1015,30 +1288,35 @@ plugin_create_applet_tag (int16 argc, char* argn[], char* argv[])
gchar* code = g_strdup_printf ("CODE=\"%s\" ", argv[i]);
applet_tag = g_strconcat (applet_tag, code, NULL);
g_free (code);
+ code = NULL;
}
else if (!g_ascii_strcasecmp (argn[i], "codebase"))
{
gchar* codebase = g_strdup_printf ("CODEBASE=\"%s\" ", argv[i]);
applet_tag = g_strconcat (applet_tag, codebase, NULL);
g_free (codebase);
+ codebase = NULL;
}
else if (!g_ascii_strcasecmp (argn[i], "archive"))
{
gchar* archive = g_strdup_printf ("ARCHIVE=\"%s\" ", argv[i]);
applet_tag = g_strconcat (applet_tag, archive, NULL);
g_free (archive);
+ archive = NULL;
}
else if (!g_ascii_strcasecmp (argn[i], "width"))
{
gchar* width = g_strdup_printf ("WIDTH=\"%s\" ", argv[i]);
applet_tag = g_strconcat (applet_tag, width, NULL);
g_free (width);
+ width = NULL;
}
else if (!g_ascii_strcasecmp (argn[i], "height"))
{
gchar* height = g_strdup_printf ("HEIGHT=\"%s\" ", argv[i]);
applet_tag = g_strconcat (applet_tag, height, NULL);
g_free (height);
+ height = NULL;
}
else
{
@@ -1046,10 +1324,14 @@ plugin_create_applet_tag (int16 argc, char* argn[], char* argv[])
// characters will pass through the pipe.
if (argv[i] != '\0')
{
- gchar* escaped = g_strescape (argv[i], NULL);
+ gchar* escaped = NULL;
+
+ escaped = g_strescape (argv[i], NULL);
parameters = g_strconcat (parameters, "<PARAM NAME=\"", argn[i],
"\" VALUE=\"", escaped, "\">", NULL);
+
g_free (escaped);
+ escaped = NULL;
}
}
}
@@ -1073,7 +1355,6 @@ plugin_send_message_to_appletviewer (GCJPluginData* data, gchar const* message)
if (data->appletviewer_alive)
{
- GError* channel_error = NULL;
gchar* newline_message = NULL;
gsize bytes_written = 0;
@@ -1086,27 +1367,34 @@ plugin_send_message_to_appletviewer (GCJPluginData* data, gchar const* message)
if (g_io_channel_write_chars (data->out_to_appletviewer,
newline_message, -1, &bytes_written,
&channel_error)
- != G_IO_STATUS_NORMAL)
- PLUGIN_ERROR_TWO ("Failed to write bytes to output channel",
- channel_error->message);
-
- if (channel_error)
+ != G_IO_STATUS_NORMAL)
{
- g_error_free (channel_error);
- channel_error = NULL;
- }
+ if (channel_error)
+ {
+ PLUGIN_ERROR_TWO ("Failed to write bytes to output channel",
+ channel_error->message);
+ g_error_free (channel_error);
+ channel_error = NULL;
+ }
+ else
+ PLUGIN_ERROR ("Failed to write bytes to output channel");
+ }
if (g_io_channel_flush (data->out_to_appletviewer, &channel_error)
!= G_IO_STATUS_NORMAL)
- PLUGIN_ERROR_TWO ("Failed to flush bytes to output channel",
- channel_error->message);
-
- if (channel_error)
{
- g_error_free (channel_error);
- channel_error = NULL;
+ if (channel_error)
+ {
+ PLUGIN_ERROR_TWO ("Failed to flush bytes to output channel",
+ channel_error->message);
+ g_error_free (channel_error);
+ channel_error = NULL;
+ }
+ else
+ PLUGIN_ERROR ("Failed to flush bytes to output channel");
}
g_free (newline_message);
+ newline_message = NULL;
g_print (" PIPE: plugin wrote %s\n", message);
}
@@ -1135,7 +1423,6 @@ plugin_stop_appletviewer (GCJPluginData* data)
if (data->appletviewer_alive)
{
// Shut down the appletviewer.
- GError* channel_error = NULL;
gsize bytes_written = 0;
if (data->out_to_appletviewer)
@@ -1143,36 +1430,45 @@ plugin_stop_appletviewer (GCJPluginData* data)
if (g_io_channel_write_chars (data->out_to_appletviewer, "shutdown",
-1, &bytes_written, &channel_error)
!= G_IO_STATUS_NORMAL)
- PLUGIN_ERROR_TWO ("Failed to write shutdown message to"
- " appletviewer", channel_error->message);
-
- if (channel_error)
{
- g_error_free (channel_error);
- channel_error = NULL;
+ if (channel_error)
+ {
+ PLUGIN_ERROR_TWO ("Failed to write shutdown message to"
+ " appletviewer", channel_error->message);
+ g_error_free (channel_error);
+ channel_error = NULL;
+ }
+ else
+ PLUGIN_ERROR ("Failed to write shutdown message to");
}
if (g_io_channel_flush (data->out_to_appletviewer, &channel_error)
!= G_IO_STATUS_NORMAL)
- PLUGIN_ERROR_TWO ("Failed to write shutdown message to"
- " appletviewer", channel_error->message);
-
- if (channel_error)
{
- g_error_free (channel_error);
- channel_error = NULL;
+ if (channel_error)
+ {
+ PLUGIN_ERROR_TWO ("Failed to write shutdown message to"
+ " appletviewer", channel_error->message);
+ g_error_free (channel_error);
+ channel_error = NULL;
+ }
+ else
+ PLUGIN_ERROR ("Failed to write shutdown message to");
}
if (g_io_channel_shutdown (data->out_to_appletviewer,
TRUE, &channel_error)
!= G_IO_STATUS_NORMAL)
- PLUGIN_ERROR_TWO ("Failed to shut down appletviewer"
- " output channel", channel_error->message);
-
- if (channel_error)
{
- g_error_free (channel_error);
- channel_error = NULL;
+ if (channel_error)
+ {
+ PLUGIN_ERROR_TWO ("Failed to shut down appletviewer"
+ " output channel", channel_error->message);
+ g_error_free (channel_error);
+ channel_error = NULL;
+ }
+ else
+ PLUGIN_ERROR ("Failed to shut down appletviewer");
}
}
@@ -1181,13 +1477,16 @@ plugin_stop_appletviewer (GCJPluginData* data)
if (g_io_channel_shutdown (data->in_from_appletviewer,
TRUE, &channel_error)
!= G_IO_STATUS_NORMAL)
- PLUGIN_ERROR_TWO ("Failed to shut down appletviewer"
- " input channel", channel_error->message);
-
- if (channel_error)
{
- g_error_free (channel_error);
- channel_error = NULL;
+ if (channel_error)
+ {
+ PLUGIN_ERROR_TWO ("Failed to shut down appletviewer"
+ " input channel", channel_error->message);
+ g_error_free (channel_error);
+ channel_error = NULL;
+ }
+ else
+ PLUGIN_ERROR ("Failed to shut down appletviewer");
}
}
}
@@ -1267,18 +1566,25 @@ plugin_data_destroy (GCJPluginData** data)
// implement and initializes a local table with browser functions that
// we may wish to call. Called once, after browser startup and before
// the first plugin instance is created.
+// The field 'initialized' is set to true once this function has
+// finished. If 'initialized' is already true at the beginning of
+// this function, then it is evident that NP_Initialize has already
+// been called. There is no need to call this function more than once and
+// this workaround avoids any duplicate calls.
NPError
NP_Initialize (NPNetscapeFuncs* browserTable, NPPluginFuncs* pluginTable)
{
PLUGIN_DEBUG ("NP_Initialize");
-
- if ((browserTable == NULL) || (pluginTable == NULL))
+
+ if (initialized)
+ return NPERR_NO_ERROR;
+ else if ((browserTable == NULL) || (pluginTable == NULL))
{
PLUGIN_ERROR ("Browser or plugin function table is NULL.");
return NPERR_INVALID_FUNCTABLE_ERROR;
}
-
+
// Ensure that the major version of the plugin API that the browser
// expects is not more recent than the major version of the API that
// we've implemented.
@@ -1307,6 +1613,45 @@ NP_Initialize (NPNetscapeFuncs* browserTable, NPPluginFuncs* pluginTable)
return NPERR_INVALID_FUNCTABLE_ERROR;
}
+ data_directory = g_strconcat(getenv("HOME"), "/.gcjwebplugin", NULL);
+ whitelist_filename = g_strconcat (data_directory, "/whitelist.txt", NULL);
+ // Make sure the plugin data directory exists, creating it if
+ // necessary.
+ if (!g_file_test (data_directory,
+ (GFileTest) (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
+ {
+ int file_error = 0;
+
+ file_error = g_mkdir (data_directory, 0700);
+ if (file_error != 0)
+ {
+ PLUGIN_ERROR_THREE ("Failed to create data directory",
+ data_directory,
+ strerror (errno));
+ return NPERR_GENERIC_ERROR;
+ }
+ }
+
+ // Open the user's documentbase whitelist.
+ whitelist_file = g_io_channel_new_file (whitelist_filename,
+ "a+", &channel_error);
+ if (!whitelist_file)
+ {
+ if (channel_error)
+ {
+ PLUGIN_ERROR_THREE ("Failed to open whitelist file",
+ whitelist_filename,
+ channel_error->message);
+ g_error_free (channel_error);
+ channel_error = NULL;
+ }
+ else
+ PLUGIN_ERROR_TWO ("Failed to open whitelist file",
+ whitelist_filename);
+
+ return NPERR_GENERIC_ERROR;
+ }
+
// Store in a local table the browser functions that we may use.
browserFunctions.version = browserTable->version;
browserFunctions.size = browserTable->size;
@@ -1339,7 +1684,8 @@ NP_Initialize (NPNetscapeFuncs* browserTable, NPPluginFuncs* pluginTable)
pluginTable->print = NewNPP_PrintProc (GCJ_Print);
pluginTable->urlnotify = NewNPP_URLNotifyProc (GCJ_URLNotify);
pluginTable->getvalue = NewNPP_GetValueProc (GCJ_GetValue);
-
+
+ initialized = true;
plugin_instance_mutex = g_mutex_new ();
PLUGIN_DEBUG ("NP_Initialize: using " APPLETVIEWER_EXECUTABLE ".");
@@ -1402,9 +1748,32 @@ NP_Shutdown (void)
PLUGIN_DEBUG ("NP_Shutdown");
// Free mutex.
- g_mutex_free (plugin_instance_mutex);
- plugin_instance_mutex = NULL;
+ if (plugin_instance_mutex)
+ {
+ g_mutex_free (plugin_instance_mutex);
+ plugin_instance_mutex = NULL;
+ }
+ if (whitelist_file)
+ {
+ g_io_channel_close (whitelist_file);
+ whitelist_file = NULL;
+ }
+
+ if (data_directory)
+ {
+ g_free (data_directory);
+ data_directory = NULL;
+ }
+
+ if (whitelist_filename)
+ {
+ g_free (whitelist_filename);
+ whitelist_filename = NULL;
+ }
+
+ initialized = false;
+
PLUGIN_DEBUG ("NP_Shutdown return");
return NPERR_NO_ERROR;