/src/html/gnc-html-webkit.c
C | 1121 lines | 809 code | 173 blank | 139 comment | 109 complexity | 21fe478d9f32b606fd8f954eee274c16 MD5 | raw file
Possible License(s): GPL-2.0
- /********************************************************************
- * gnc-html-webkit.c -- gnucash report renderer using webkit *
- * *
- * Copyright (C) 2000 Bill Gribble <grib@billgribble.com> *
- * Copyright (C) 2001 Linas Vepstas <linas@linas.org> *
- * Copyright (C) 2009 Phil Longstaff <plongstaff@rogers.com> *
- * *
- * 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, contact: *
- * *
- * Free Software Foundation Voice: +1-617-542-5942 *
- * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
- * Boston, MA 02110-1301, USA gnu@gnu.org *
- ********************************************************************/
- #include "config.h"
- #include "platform.h"
- #include <gtk/gtk.h>
- #include <glib/gi18n.h>
- #include <glib/gstdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <regex.h>
- #include <libguile.h>
- #include <webkit/webkit.h>
- #include "Account.h"
- #include "gnc-gui-query.h"
- #include "gnc-engine.h"
- #include "gnc-html.h"
- #include "gnc-html-webkit.h"
- #include "gnc-html-history.h"
- #include "gnc-html-graph-gog-webkit.h"
- #include "print-session.h"
- G_DEFINE_TYPE(GncHtmlWebkit, gnc_html_webkit, GNC_TYPE_HTML )
- static void gnc_html_webkit_dispose( GObject* obj );
- static void gnc_html_webkit_finalize( GObject* obj );
- static void gnc_html_webkit_class_init( GncHtmlWebkitClass* klass );
- static void gnc_html_webkit_init( GncHtmlWebkit* gs );
- #define GNC_HTML_WEBKIT_GET_PRIVATE(o) (GNC_HTML_WEBKIT(o)->priv)
- #include "gnc-html-webkit-p.h"
- /* indicates the debugging module that this .o belongs to. */
- static QofLogModule log_module = GNC_MOD_HTML;
- /* hashes for URLType -> protocol and protocol -> URLType */
- //extern GHashTable* gnc_html_type_to_proto_hash;
- extern GHashTable* gnc_html_proto_to_type_hash;
- /* hashes an HTML <object classid="ID"> classid to a handler function */
- extern GHashTable* gnc_html_object_handlers;
- /* hashes handlers for loading different URLType data */
- extern GHashTable* gnc_html_stream_handlers;
- /* hashes handlers for handling different URLType data */
- extern GHashTable* gnc_html_url_handlers;
- static char error_404_format[] = "<html><body><h3>%s</h3><p>%s</body></html>";
- static char error_404_title[] = N_("Not found");
- static char error_404_body[] = N_("The specified URL could not be loaded.");
- #define BASE_URI_NAME "base-uri"
- static WebKitNavigationResponse webkit_navigation_requested_cb(
- WebKitWebView* web_view,
- WebKitWebFrame* frame,
- WebKitNetworkRequest* request,
- gpointer user_data );
- static void webkit_on_url_cb( WebKitWebView* web_view, gchar* title, gchar* url,
- gpointer data );
- static gchar* handle_embedded_object( GncHtmlWebkit* self, gchar* html_str );
- #if 0
- static void gnc_html_set_base_cb( GtkHTML* gtkhtml, const gchar* base, gpointer data );
- static void gnc_html_link_clicked_cb( GtkHTML* html, const gchar* url, gpointer data );
- static gboolean gnc_html_object_requested_cb( GtkHTML* html, GtkHTMLEmbedded* eb,
- gpointer data );
- #endif
- static int gnc_html_button_press_cb( GtkWidget* widg, GdkEventButton* event,
- gpointer user_data );
- static void impl_webkit_show_url( GncHtml* self, URLType type,
- const gchar* location, const gchar* label,
- gboolean new_window_hint );
- static void impl_webkit_show_data( GncHtml* self, const gchar* data, int datalen );
- static void impl_webkit_reload( GncHtml* self );
- static void impl_webkit_copy_to_clipboard( GncHtml* self );
- static gboolean impl_webkit_export_to_file( GncHtml* self, const gchar* filepath );
- static void impl_webkit_print( GncHtml* self, const gchar* jobname );
- static void impl_webkit_cancel( GncHtml* self );
- static void impl_webkit_set_parent( GncHtml* self, GtkWindow* parent );
- static void
- gnc_html_webkit_init( GncHtmlWebkit* self )
- {
- GncHtmlWebkitPrivate* priv;
- GncHtmlWebkitPrivate* new_priv;
- WebKitWebSettings* webkit_settings = NULL;
- const char* default_font_family = NULL;
- new_priv = g_realloc( GNC_HTML(self)->priv, sizeof(GncHtmlWebkitPrivate) );
- priv = self->priv = new_priv;
- GNC_HTML(self)->priv = (GncHtmlPrivate*)priv;
- priv->html_string = NULL;
- priv->web_view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- /* Get the default font family from GtkStyle of a GtkWidget(priv-web_view). */
- default_font_family = pango_font_description_get_family( gtk_rc_get_style(GTK_WIDGET(priv->web_view))->font_desc );
- /* Set default webkit settings */
- webkit_settings = webkit_web_view_get_settings (priv->web_view);
- g_object_set (G_OBJECT(webkit_settings), "default-encoding", "utf-8", NULL);
- if (default_font_family == NULL)
- {
- PWARN("webkit_settings: Cannot get default font family.");
- }
- else
- {
- g_object_set (G_OBJECT(webkit_settings),
- "default-font-family", default_font_family,
- NULL);
- PINFO("webkit_settings: Set default font to [%s]", default_font_family);
- }
- gtk_container_add( GTK_CONTAINER(priv->base.container),
- GTK_WIDGET(priv->web_view) );
- g_object_ref_sink( priv->base.container );
- /* signals */
- g_signal_connect( priv->web_view, "navigation-requested",
- G_CALLBACK(webkit_navigation_requested_cb),
- self);
- g_signal_connect( priv->web_view, "hovering-over-link",
- G_CALLBACK(webkit_on_url_cb),
- self );
- #if 0
- g_signal_connect( priv->html, "set_base",
- G_CALLBACK(gnc_html_set_base_cb),
- self);
- g_signal_connect(priv->html, "link_clicked",
- G_CALLBACK(gnc_html_link_clicked_cb),
- self);
- g_signal_connect (priv->html, "object_requested",
- G_CALLBACK (gnc_html_object_requested_cb),
- self);
- g_signal_connect (priv->html, "button_press_event",
- G_CALLBACK (gnc_html_button_press_cb),
- self);
- g_signal_connect (priv->html, "submit",
- G_CALLBACK(gnc_html_submit_cb),
- self);
- #endif
- LEAVE("retval %p", self);
- }
- static void
- gnc_html_webkit_class_init( GncHtmlWebkitClass* klass )
- {
- GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
- GncHtmlClass* html_class = GNC_HTML_CLASS(klass);
- gobject_class->dispose = gnc_html_webkit_dispose;
- gobject_class->finalize = gnc_html_webkit_finalize;
- html_class->show_url = impl_webkit_show_url;
- html_class->show_data = impl_webkit_show_data;
- html_class->reload = impl_webkit_reload;
- html_class->copy_to_clipboard = impl_webkit_copy_to_clipboard;
- html_class->export_to_file = impl_webkit_export_to_file;
- html_class->print = impl_webkit_print;
- html_class->cancel = impl_webkit_cancel;
- html_class->set_parent = impl_webkit_set_parent;
- // Initialize graphing support
- gnc_html_graph_gog_webkit_init();
- }
- static void
- gnc_html_webkit_dispose( GObject* obj )
- {
- GncHtmlWebkit* self = GNC_HTML_WEBKIT(obj);
- GncHtmlWebkitPrivate* priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
- if ( priv->web_view != NULL )
- {
- gtk_container_remove( GTK_CONTAINER(priv->base.container),
- GTK_WIDGET(priv->web_view) );
- priv->web_view = NULL;
- }
- if ( priv->html_string != NULL )
- {
- g_free( priv->html_string );
- priv->html_string = NULL;
- }
- G_OBJECT_CLASS(gnc_html_webkit_parent_class)->dispose( obj );
- }
- static void
- gnc_html_webkit_finalize( GObject* obj )
- {
- GncHtmlWebkit* self = GNC_HTML_WEBKIT(obj);
- // if( self->priv != NULL ) {
- // g_free( self->priv );
- self->priv = NULL;
- // }
- G_OBJECT_CLASS(gnc_html_webkit_parent_class)->finalize( obj );
- }
- /*****************************************************************************/
- static char*
- extract_base_name(URLType type, const gchar* path)
- {
- gchar machine_rexp[] = "^(//[^/]*)/*(/.*)?$";
- gchar path_rexp[] = "^/*(.*)/+([^/]*)$";
- regex_t compiled_m, compiled_p;
- regmatch_t match[4];
- gchar * machine = NULL, * location = NULL, * base = NULL;
- gchar * basename = NULL;
- DEBUG(" ");
- if (!path) return NULL;
- regcomp(&compiled_m, machine_rexp, REG_EXTENDED);
- regcomp(&compiled_p, path_rexp, REG_EXTENDED);
- if (!safe_strcmp (type, URL_TYPE_HTTP) ||
- !safe_strcmp (type, URL_TYPE_SECURE) ||
- !safe_strcmp (type, URL_TYPE_FTP))
- {
- /* step 1: split the machine name away from the path
- * components */
- if (!regexec(&compiled_m, path, 4, match, 0))
- {
- /* $1 is the machine name */
- if (match[1].rm_so != -1)
- {
- machine = g_strndup(path + match[1].rm_so,
- match[1].rm_eo - match[1].rm_so);
- }
- /* $2 is the path */
- if (match[2].rm_so != -1)
- {
- location = g_strndup(path + match[2].rm_so,
- match[2].rm_eo - match[2].rm_so);
- }
- }
- }
- else
- {
- location = g_strdup(path);
- }
- /* step 2: split up the path into prefix and file components */
- if (location)
- {
- if (!regexec(&compiled_p, location, 4, match, 0))
- {
- if (match[1].rm_so != -1)
- {
- base = g_strndup(location + match[1].rm_so,
- match[1].rm_eo - match[1].rm_so);
- }
- else
- {
- base = NULL;
- }
- }
- }
- regfree(&compiled_m);
- regfree(&compiled_p);
- if (machine)
- {
- if (base && (strlen(base) > 0))
- {
- basename = g_strconcat(machine, "/", base, "/", NULL);
- }
- else
- {
- basename = g_strconcat(machine, "/", NULL);
- }
- }
- else
- {
- if (base && (strlen(base) > 0))
- {
- basename = g_strdup(base);
- }
- else
- {
- basename = NULL;
- }
- }
- g_free(machine);
- g_free(base);
- g_free(location);
- return basename;
- }
- static gboolean
- http_allowed()
- {
- return TRUE;
- }
- static gboolean
- https_allowed()
- {
- return TRUE;
- }
- static gchar*
- handle_embedded_object( GncHtmlWebkit* self, gchar* html_str )
- {
- // Find the <object> tag and get the classid from it. This will provide the correct
- // object callback handler. Pass the <object> entity text to the handler. What should
- // come back is embedded image information.
- gchar* object_tag;
- gchar* end_object_tag;
- gchar* object_contents;
- gchar* html_str_start;
- gchar* html_str_middle;
- gchar* html_str_result;
- gchar* classid;
- gchar* classid_end;
- gchar* object_classid;
- GncHTMLObjectCB h;
- object_tag = g_strstr_len( html_str, -1, "<object classid=" );
- if ( object_tag == NULL )
- {
- // Hmmm... no object tag
- return html_str;
- }
- classid = object_tag + strlen( "<object classid=" ) + 1;
- classid_end = g_strstr_len( classid, -1, "\"" );
- object_classid = g_strndup( classid, (classid_end - classid) );
- end_object_tag = g_strstr_len( object_tag, -1, "</object>" );
- if ( end_object_tag == NULL )
- {
- // Hmmm... no object end tag
- return html_str;
- }
- end_object_tag += strlen( "</object>" );
- object_contents = g_strndup( object_tag, (end_object_tag - object_tag) );
- h = g_hash_table_lookup( gnc_html_object_handlers, object_classid );
- if ( h != NULL )
- {
- (void)h( GNC_HTML(self), object_contents, &html_str_middle );
- }
- else
- {
- html_str_middle = g_strdup_printf( "No handler found for classid \"%s\"", object_classid );
- }
- html_str_start = g_strndup( html_str, (object_tag - html_str) );
- html_str_result = g_strdup_printf( "%s%s%s", html_str_start, html_str_middle, end_object_tag );
- g_free( html_str_start );
- g_free( html_str_middle );
- return html_str_result;
- }
- /********************************************************************
- * load_to_stream : actually do the work of loading the HTML
- * or binary data referenced by a URL and feeding it into the webkit
- * widget.
- ********************************************************************/
- static void
- load_to_stream( GncHtmlWebkit* self, URLType type,
- const gchar* location, const gchar* label )
- {
- gchar* fdata = NULL;
- int fdata_len = 0;
- GncHtmlWebkitPrivate* priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
- DEBUG( "type %s, location %s, label %s", type ? type : "(null)",
- location ? location : "(null)", label ? label : "(null)");
- g_return_if_fail( self != NULL );
- if ( gnc_html_stream_handlers != NULL )
- {
- GncHTMLStreamCB stream_handler;
- stream_handler = g_hash_table_lookup( gnc_html_stream_handlers, type );
- if ( stream_handler )
- {
- gboolean ok = stream_handler( location, &fdata, &fdata_len );
- if ( ok )
- {
- fdata = fdata ? fdata : g_strdup( "" );
- // Until webkitgtk supports download requests, look for "<object classid="
- // indicating the beginning of an embedded graph. If found, handle it
- if ( g_strstr_len( fdata, -1, "<object classid=" ) != NULL )
- {
- gchar* new_fdata;
- new_fdata = handle_embedded_object( self, fdata );
- g_free( fdata );
- fdata = new_fdata;
- }
- // Save a copy for export purposes
- if ( priv->html_string != NULL )
- {
- g_free( priv->html_string );
- }
- priv->html_string = g_strdup( fdata );
- impl_webkit_show_data( GNC_HTML(self), fdata, strlen(fdata) );
- // webkit_web_view_load_html_string( priv->web_view, fdata, BASE_URI_NAME );
- }
- else
- {
- fdata = fdata ? fdata :
- g_strdup_printf( error_404_format,
- _(error_404_title), _(error_404_body) );
- webkit_web_view_load_html_string( priv->web_view, fdata, BASE_URI_NAME );
- }
- g_free( fdata );
- if ( label )
- {
- while ( gtk_events_pending() )
- {
- gtk_main_iteration();
- }
- /* No action required: Webkit jumps to the anchor on its own. */
- }
- return;
- }
- }
- do
- {
- if ( !safe_strcmp( type, URL_TYPE_SECURE ) ||
- !safe_strcmp( type, URL_TYPE_HTTP ) )
- {
- if ( !safe_strcmp( type, URL_TYPE_SECURE ) )
- {
- if ( !https_allowed() )
- {
- gnc_error_dialog( priv->base.parent, "%s",
- _("Secure HTTP access is disabled. "
- "You can enable it in the Network section of "
- "the Preferences dialog."));
- break;
- }
- }
- if ( !http_allowed() )
- {
- gnc_error_dialog( priv->base.parent, "%s",
- _("Network HTTP access is disabled. "
- "You can enable it in the Network section of "
- "the Preferences dialog."));
- }
- else
- {
- char *fullurl;
- fullurl = gnc_build_url( type, location, label );
- }
- }
- else
- {
- PWARN( "load_to_stream for inappropriate type\n"
- "\turl = '%s#%s'\n",
- location ? location : "(null)",
- label ? label : "(null)" );
- fdata = g_strdup_printf( error_404_format,
- _(error_404_title), _(error_404_body) );
- webkit_web_view_load_html_string( priv->web_view, fdata, BASE_URI_NAME );
- g_free( fdata );
- }
- }
- while ( FALSE );
- }
- #if 0
- /********************************************************************
- * gnc_html_link_clicked_cb - called when user left-clicks on html
- * anchor.
- ********************************************************************/
- static void
- gnc_html_link_clicked_cb( GtkHTML* html, const gchar* url, gpointer data )
- {
- URLType type;
- gchar* location = NULL;
- gchar* label = NULL;
- GncHtmlWebkit* self = GNC_HTML_WEBKIT(data);
- DEBUG("Clicked %s", url);
- type = gnc_html_parse_url( GNC_HTML(self), url, &location, &label );
- gnc_html_show_url( GNC_HTML(self), type, location, label, 0 );
- g_free( location );
- g_free( label );
- }
- #endif
- /********************************************************************
- * webkit_navigation_requested_cb - called when a URL needs to be
- * loaded within the loading of a page (embedded image).
- ********************************************************************/
- static WebKitNavigationResponse
- webkit_navigation_requested_cb( WebKitWebView* web_view, WebKitWebFrame* frame,
- WebKitNetworkRequest* request,
- gpointer data )
- {
- URLType type;
- gchar* location = NULL;
- gchar* label = NULL;
- GncHtmlWebkit* self = GNC_HTML_WEBKIT(data);
- const gchar* url = webkit_network_request_get_uri( request );
- ENTER( "requesting %s", url );
- if ( strcmp( url, BASE_URI_NAME ) == 0 )
- {
- LEAVE("URI is %s", BASE_URI_NAME);
- return WEBKIT_NAVIGATION_RESPONSE_ACCEPT;
- }
- type = gnc_html_parse_url( GNC_HTML(self), url, &location, &label );
- if ( strcmp( type, "file" ) == 0 )
- {
- LEAVE("URI type is 'file'");
- return WEBKIT_NAVIGATION_RESPONSE_ACCEPT;
- }
- gnc_html_show_url( GNC_HTML(self), type, location, label, 0 );
- // load_to_stream( self, type, location, label );
- g_free( location );
- g_free( label );
- LEAVE("");
- return WEBKIT_NAVIGATION_RESPONSE_IGNORE;
- }
- #if 0
- /********************************************************************
- * gnc_html_object_requested_cb - called when an applet needs to be
- * loaded.
- ********************************************************************/
- static gboolean
- gnc_html_object_requested_cb( GtkHTML* html, GtkHTMLEmbedded* eb,
- gpointer data )
- {
- GncHtmlWebkit* self = GNC_HTML_WEBKIT(data);
- GncHTMLObjectCB h;
- DEBUG( " " );
- if ( !eb || !(eb->classid) || !gnc_html_object_handlers ) return FALSE;
- h = g_hash_table_lookup( gnc_html_object_handlers, eb->classid );
- if ( h )
- {
- return h( GNC_HTML(self), eb, data );
- }
- else
- {
- return FALSE;
- }
- }
- #endif
- /********************************************************************
- * webkit_on_url_cb - called when user rolls over html anchor
- ********************************************************************/
- static void
- webkit_on_url_cb( WebKitWebView* web_view, gchar* title, gchar* url, gpointer data )
- {
- GncHtmlWebkit* self = GNC_HTML_WEBKIT(data);
- GncHtmlWebkitPrivate* priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
- DEBUG( "Rollover %s", url ? url : "(null)" );
- g_free( priv->base.current_link );
- priv->base.current_link = g_strdup( url );
- if ( priv->base.flyover_cb )
- {
- (priv->base.flyover_cb)( GNC_HTML(self), url, priv->base.flyover_cb_data );
- }
- }
- #if 0
- /********************************************************************
- * gnc_html_set_base_cb
- ********************************************************************/
- static void
- gnc_html_set_base_cb( GtkHTML* gtkhtml, const gchar* base,
- gpointer data )
- {
- GncHtmlWebkit* self = GNC_HTML_WEBKIT(data);
- GncHtmlWebkitPrivate* priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
- URLType type;
- gchar* location = NULL;
- gchar* label = NULL;
- DEBUG( "Setting base location to %s", base );
- type = gnc_html_parse_url( GNC_HTML(self), base, &location, &label );
- g_free( priv->base.base_location );
- g_free( label );
- priv->base.base_type = type;
- priv->base.base_location = location;
- }
- #endif
- /********************************************************************
- * gnc_html_button_press_cb
- * mouse button callback (if any)
- ********************************************************************/
- static int
- gnc_html_button_press_cb( GtkWidget* widg, GdkEventButton* event,
- gpointer user_data )
- {
- GncHtmlWebkit* self = GNC_HTML_WEBKIT(user_data);
- GncHtmlWebkitPrivate* priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
- DEBUG( "Button Press" );
- if ( priv->base.button_cb != NULL )
- {
- (priv->base.button_cb)( GNC_HTML(self), event, priv->base.button_cb_data );
- return TRUE;
- }
- else
- {
- return FALSE;
- }
- }
- /********************************************************************
- * gnc_html_open_scm
- * insert some scheme-generated HTML
- ********************************************************************/
- static void
- gnc_html_open_scm( GncHtmlWebkit* self, const gchar * location,
- const gchar * label, int newwin )
- {
- PINFO("location='%s'", location ? location : "(null)");
- }
- /********************************************************************
- * gnc_html_show_data
- * display some HTML that the creator of the gnc-html got from
- * somewhere.
- ********************************************************************/
- static void
- impl_webkit_show_data( GncHtml* self, const gchar* data, int datalen )
- {
- GncHtmlWebkitPrivate* priv;
- #if HAVE(WEBKIT_WEB_VIEW_LOAD_URI)
- #define TEMPLATE_REPORT_FILE_NAME "gnc-report-XXXXXX.html"
- int fd;
- gchar* uri;
- gchar *filename;
- #endif
- g_return_if_fail( self != NULL );
- g_return_if_fail( GNC_IS_HTML_WEBKIT(self) );
- ENTER( "datalen %d, data %20.20s", datalen, data );
- priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
- #if HAVE(WEBKIT_WEB_VIEW_LOAD_URI)
- /* Export the HTML to a file and load the file URI. On Linux, this seems to get around some
- security problems (otherwise, it can complain that embedded images aren't permitted to be
- viewed because they are local resources). On Windows, this allows the embedded images to
- be viewed (maybe for the same reason as on Linux, but I haven't found where it puts those
- messages. */
- filename = g_build_filename(g_get_tmp_dir(), TEMPLATE_REPORT_FILE_NAME, (gchar *)NULL);
- fd = g_mkstemp( filename );
- impl_webkit_export_to_file( self, filename );
- close( fd );
- uri = g_strdup_printf( "file:///%s", filename );
- g_free(filename);
- DEBUG("Loading uri '%s'", uri);
- webkit_web_view_load_uri( priv->web_view, uri );
- g_free( uri );
- #else
- webkit_web_view_load_html_string( priv->web_view, data, BASE_URI_NAME );
- #endif
- LEAVE("");
- }
- /********************************************************************
- * gnc_html_show_url
- *
- * open a URL. This is called when the user clicks a link or
- * for the creator of the gnc_html window to explicitly request
- * a URL.
- ********************************************************************/
- static void
- impl_webkit_show_url( GncHtml* self, URLType type,
- const gchar* location, const gchar* label,
- gboolean new_window_hint )
- {
- GncHTMLUrlCB url_handler;
- gboolean new_window;
- GncHtmlWebkitPrivate* priv;
- g_return_if_fail( self != NULL );
- g_return_if_fail( GNC_IS_HTML_WEBKIT(self) );
- g_return_if_fail( location != NULL );
- priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
- /* make sure it's OK to show this URL type in this window */
- if ( new_window_hint == 0 )
- {
- if ( priv->base.urltype_cb )
- {
- new_window = !((priv->base.urltype_cb)( type ));
- }
- else
- {
- new_window = FALSE;
- }
- }
- else
- {
- new_window = TRUE;
- }
- if ( !new_window )
- {
- gnc_html_cancel( GNC_HTML(self) );
- }
- if ( gnc_html_url_handlers )
- {
- url_handler = g_hash_table_lookup( gnc_html_url_handlers, type );
- }
- else
- {
- url_handler = NULL;
- }
- if ( url_handler )
- {
- GNCURLResult result;
- gboolean ok;
- result.load_to_stream = FALSE;
- result.url_type = type;
- result.location = NULL;
- result.label = NULL;
- result.base_type = URL_TYPE_FILE;
- result.base_location = NULL;
- result.error_message = NULL;
- ok = url_handler( location, label, new_window, &result );
- if ( !ok )
- {
- if ( result.error_message )
- {
- gnc_error_dialog( priv->base.parent, "%s", result.error_message );
- }
- else
- {
- /* %s is a URL (some location somewhere). */
- gnc_error_dialog( priv->base.parent, _("There was an error accessing %s."), location );
- }
- if ( priv->base.load_cb )
- {
- priv->base.load_cb( GNC_HTML(self), result.url_type,
- location, label, priv->base.load_cb_data );
- }
- }
- else if ( result.load_to_stream )
- {
- gnc_html_history_node *hnode;
- const char *new_location;
- const char *new_label;
- new_location = result.location ? result.location : location;
- new_label = result.label ? result.label : label;
- hnode = gnc_html_history_node_new( result.url_type, new_location, new_label );
- gnc_html_history_append( priv->base.history, hnode );
- g_free( priv->base.base_location );
- priv->base.base_type = result.base_type;
- priv->base.base_location =
- g_strdup( extract_base_name( result.base_type, new_location ) );
- DEBUG( "resetting base location to %s",
- priv->base.base_location ? priv->base.base_location : "(null)" );
- load_to_stream( GNC_HTML_WEBKIT(self), result.url_type,
- new_location, new_label );
- if ( priv->base.load_cb != NULL )
- {
- priv->base.load_cb( GNC_HTML(self), result.url_type,
- new_location, new_label, priv->base.load_cb_data );
- }
- }
- g_free( result.location );
- g_free( result.label );
- g_free( result.base_location );
- g_free( result.error_message );
- return;
- }
- if ( safe_strcmp( type, URL_TYPE_SCHEME ) == 0 )
- {
- gnc_html_open_scm( GNC_HTML_WEBKIT(self), location, label, new_window );
- }
- else if ( safe_strcmp( type, URL_TYPE_JUMP ) == 0 )
- {
- /* Webkit jumps to the anchor on its own */
- }
- else if ( safe_strcmp( type, URL_TYPE_SECURE ) == 0 ||
- safe_strcmp( type, URL_TYPE_HTTP ) == 0 ||
- safe_strcmp( type, URL_TYPE_FILE ) == 0 )
- {
- do
- {
- if ( safe_strcmp( type, URL_TYPE_SECURE ) == 0 )
- {
- if ( !https_allowed() )
- {
- gnc_error_dialog( priv->base.parent, "%s",
- _("Secure HTTP access is disabled. "
- "You can enable it in the Network section of "
- "the Preferences dialog.") );
- break;
- }
- }
- if ( safe_strcmp( type, URL_TYPE_HTTP ) == 0 )
- {
- if ( !http_allowed() )
- {
- gnc_error_dialog( priv->base.parent, "%s",
- _("Network HTTP access is disabled. "
- "You can enable it in the Network section of "
- "the Preferences dialog.") );
- break;
- }
- }
- priv->base.base_type = type;
- if ( priv->base.base_location != NULL ) g_free( priv->base.base_location );
- priv->base.base_location = extract_base_name( type, location );
- /* FIXME : handle new_window = 1 */
- gnc_html_history_append( priv->base.history,
- gnc_html_history_node_new( type, location, label ) );
- load_to_stream( GNC_HTML_WEBKIT(self), type, location, label );
- }
- while ( FALSE );
- }
- else
- {
- PERR( "URLType %s not supported.", type );
- }
- if ( priv->base.load_cb != NULL )
- {
- (priv->base.load_cb)( GNC_HTML(self), type, location, label, priv->base.load_cb_data );
- }
- }
- /********************************************************************
- * gnc_html_reload
- * reload the current page
- ********************************************************************/
- static void
- impl_webkit_reload( GncHtml* self )
- {
- gnc_html_history_node * n;
- GncHtmlWebkitPrivate* priv;
- g_return_if_fail( self != NULL );
- g_return_if_fail( GNC_IS_HTML_WEBKIT(self) );
- priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
- n = gnc_html_history_get_current( priv->base.history );
- if ( n != NULL )
- {
- gnc_html_show_url( self, n->type, n->location, n->label, 0 );
- }
- }
- /********************************************************************
- * gnc_html_new
- * create and set up a new webkit widget.
- ********************************************************************/
- GncHtml*
- gnc_html_webkit_new( void )
- {
- GncHtmlWebkit* self = g_object_new( GNC_TYPE_HTML_WEBKIT, NULL );
- GncHtmlWebkitPrivate* priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
- return GNC_HTML(self);
- }
- /********************************************************************
- * gnc_html_cancel
- * cancel any outstanding HTML fetch requests.
- ********************************************************************/
- static gboolean
- webkit_cancel_helper(gpointer key, gpointer value, gpointer user_data)
- {
- g_free(key);
- g_list_free((GList *)value);
- return TRUE;
- }
- static void
- impl_webkit_cancel( GncHtml* self )
- {
- GncHtmlWebkitPrivate* priv;
- g_return_if_fail( self != NULL );
- g_return_if_fail( GNC_IS_HTML_WEBKIT(self) );
- priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
- /* remove our own references to requests */
- //gnc_http_cancel_requests( priv->http );
- g_hash_table_foreach_remove( priv->base.request_info, webkit_cancel_helper, NULL );
- }
- static void
- impl_webkit_copy_to_clipboard( GncHtml* self )
- {
- GncHtmlWebkitPrivate* priv;
- g_return_if_fail( self != NULL );
- g_return_if_fail( GNC_IS_HTML_WEBKIT(self) );
- priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
- if ( webkit_web_view_can_copy_clipboard( priv->web_view ) )
- {
- webkit_web_view_copy_clipboard( priv->web_view );
- }
- }
- /**************************************************************
- * gnc_html_export_to_file
- *
- * @param self GncHtmlWebkit object
- * @param filepath Where to write the HTML
- * @return TRUE if successful, FALSE if unsucessful
- **************************************************************/
- static gboolean
- impl_webkit_export_to_file( GncHtml* self, const char *filepath )
- {
- FILE *fh;
- GncHtmlWebkitPrivate* priv;
- g_return_val_if_fail( self != NULL, FALSE );
- g_return_val_if_fail( GNC_IS_HTML_WEBKIT(self), FALSE );
- g_return_val_if_fail( filepath != NULL, FALSE );
- priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
- if ( priv->html_string == NULL )
- {
- return FALSE;
- }
- fh = g_fopen( filepath, "w" );
- if ( fh != NULL )
- {
- gint written;
- gint len = strlen( priv->html_string );
- written = fwrite( priv->html_string, 1, len, fh );
- fclose (fh);
- if ( written != len )
- {
- return FALSE;
- }
- return TRUE;
- }
- else
- {
- return FALSE;
- }
- }
- /**
- * Prints the current page.
- *
- * If printing on WIN32, in order to prevent the font from being tiny, (see bug #591177),
- * A GtkPrintOperation object needs to be created so that the unit can be set, and then
- * webkit_web_frame_print_full() needs to be called to use that GtkPrintOperation. On
- * other platforms (specifically linux - not sure about MacOSX), the version of webkit may
- * not contain the function webkit_web_frame_print_full(), so webkit_web_frame_print() is
- * called instead (the font size problem doesn't show up on linux).
- *
- * @param self HTML renderer object
- */
- static void
- impl_webkit_print( GncHtml* self, const gchar* jobname )
- {
- #if !HAVE(WEBKIT_WEB_FRAME_PRINT_FULL)
- extern void webkit_web_frame_print( WebKitWebFrame * frame );
- #endif
- GncHtmlWebkitPrivate* priv;
- WebKitWebFrame* frame;
- #if HAVE(WEBKIT_WEB_FRAME_PRINT_FULL)
- GtkPrintOperation* op = gtk_print_operation_new();
- GError* error = NULL;
- #endif
- priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
- frame = webkit_web_view_get_main_frame( priv->web_view );
- #if HAVE(WEBKIT_WEB_FRAME_PRINT_FULL)
- gnc_print_operation_init( op, jobname );
- #ifdef G_OS_WIN32
- gtk_print_operation_set_unit( op, GTK_UNIT_POINTS );
- #endif
- webkit_web_frame_print_full( frame, op, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, &error );
- g_object_unref( op );
- if ( error != NULL )
- {
- GtkWidget* window = gtk_widget_get_toplevel( GTK_WIDGET(priv->web_view) );
- GtkWidget* dialog = gtk_message_dialog_new( GTK_WIDGET_TOPLEVEL(window) ? GTK_WINDOW(window) : NULL,
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_CLOSE,
- "%s", error->message );
- g_error_free( error );
- g_signal_connect( dialog, "response", G_CALLBACK(gtk_widget_destroy), NULL);
- gtk_widget_show( dialog );
- }
- #else
- webkit_web_frame_print( frame );
- #endif
- }
- static void
- impl_webkit_set_parent( GncHtml* self, GtkWindow* parent )
- {
- GncHtmlWebkitPrivate* priv;
- g_return_if_fail( self != NULL );
- g_return_if_fail( GNC_IS_HTML_WEBKIT(self) );
- priv = GNC_HTML_WEBKIT_GET_PRIVATE(self);
- priv->base.parent = GTK_WIDGET(parent);
- }