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; }
static PyObject * _wrap_gnc_html_webkit_show_data(PyObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "html", "data", "datalen", NULL }; PyGObject *html; char *data; int datalen; GncHtmlPrivate *priv_html; GncHtmlWebkitPrivate *priv; //fprintf(stderr,"webkit show data called 1\n"); if (!PyArg_ParseTupleAndKeywords(args, kwargs,"Osi:Gnc.HtmlWebkit.show_data", kwlist, &html, &data, &datalen)) return NULL; //fprintf(stderr,"webkit show data called 2\n"); // we now call the gnc-html class pointer //gnc_html_webkit_show_data(GNC_HTML_WEBKIT(html->obj), data, datalen); GncHtml* gself_html = GNC_HTML(html->obj); GncHtmlWebkit* gself = GNC_HTML_WEBKIT(html->obj); fprintf(stderr,"html self is %p\n",(void *)gself_html); fprintf(stderr,"html self is %d\n",GNC_IS_HTML(gself_html)); fprintf(stderr,"html self class is %p\n",(void *)GNC_HTML_GET_CLASS(gself_html)); fprintf(stderr,"html self show_data is %p\n",(void *)(GNC_HTML_GET_CLASS(gself_html)->show_data)); fprintf(stderr,"webkit self is %p\n",(void *)gself); fprintf(stderr,"webkit self is %d\n",GNC_IS_HTML(gself)); fprintf(stderr,"webkit self class is %p\n",(void *)GNC_HTML_WEBKIT_GET_CLASS(gself)); // so this does not exist - only the parent class GncHtml defines the show_data!! //fprintf(stderr,"webkit self show_data is %p\n",(void *)(GNC_HTML_WEBKIT_GET_CLASS(gself)->show_data)); // this appears to be the way we call should call it rather than // direct pointer call // great - inspection of code show this only displays stuff if priv->html_string is set // note that the dispose function frees this priv_html = GNC_HTML_GET_PRIVATE(gself_html); fprintf(stderr,"html self priv %p\n",(char *)&(gself_html->priv)); fprintf(stderr,"html self priv is %p\n",(void *)priv_html); priv = GNC_HTML_WEBKIT_GET_PRIVATE(gself); priv->html_string = g_strdup(data); fprintf(stderr,"html self html struct len %lx\n", sizeof(GncHtml)); fprintf(stderr,"html self htmlwebkitstruct len %lx\n", sizeof(GncHtmlWebkit)); fprintf(stderr,"webkit self priv %p\n",(char *)&(gself->priv)); fprintf(stderr,"webkit self priv offset %llx\n",((char *)((char *)&(gself->priv)-(char *)gself))); fprintf(stderr,"webkit self priv is %p\n",(void *)priv); fprintf(stderr,"webkit self priv html_string is %p\n",(void *)&(priv->html_string)); fprintf(stderr,"webkit self priv html_string offset %llx\n",((char *)&(priv->html_string)-(char *)priv)); gnc_html_show_data( GNC_HTML(gself), data, datalen ); Py_INCREF(Py_None); return Py_None; }
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 ); }
static void gnc_html_dispose( GObject* obj ) { GncHtml* self = GNC_HTML(obj); GncHtmlPrivate* priv = GNC_HTML_GET_PRIVATE(self); if ( priv->container != NULL ) { gtk_widget_destroy( GTK_WIDGET(priv->container) ); g_object_unref( G_OBJECT(priv->container) ); priv->container = NULL; } if ( priv->request_info != NULL ) { g_hash_table_destroy( priv->request_info ); priv->request_info = NULL; } if ( priv->history != NULL ) { gnc_html_history_destroy( priv->history ); priv->history = NULL; } G_OBJECT_CLASS(gnc_html_parent_class)->dispose( obj ); }
static void gnc_html_finalize( GObject* obj ) { GncHtml* self = GNC_HTML(obj); if ( self->priv != NULL ) { g_free( self->priv ); self->priv = NULL; } G_OBJECT_CLASS(gnc_html_parent_class)->finalize( obj ); }
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 ); } }
/******************************************************************** * gnc_html_button_press_cb * mouse button callback (if any) ********************************************************************/ #if 0 /* Not Used */ 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; } }
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; }
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; } }
GncHtml* gnc_html_webkit_new( void ) { GncHtmlWebkit* self = g_object_new( GNC_TYPE_HTML_WEBKIT, NULL ); return GNC_HTML(self); }
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 ( g_strcmp0( type, URL_TYPE_SCHEME ) == 0 ) { gnc_html_open_scm( GNC_HTML_WEBKIT(self), location, label, new_window ); } else if ( g_strcmp0( type, URL_TYPE_JUMP ) == 0 ) { /* Webkit jumps to the anchor on its own */ } else if ( g_strcmp0( type, URL_TYPE_SECURE ) == 0 || g_strcmp0( type, URL_TYPE_HTTP ) == 0 || g_strcmp0( type, URL_TYPE_FILE ) == 0 ) { do { if ( g_strcmp0( 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 ( g_strcmp0( 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 ); } }
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 ( !g_strcmp0( type, URL_TYPE_SECURE ) || !g_strcmp0( type, URL_TYPE_HTTP ) ) { if ( !g_strcmp0( 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 { 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 ); }
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* remainder_str = html_str; gchar* object_tag; gchar* end_object_tag; gchar* object_contents; gchar* html_str_start = NULL; gchar* html_str_middle; gchar* html_str_result = NULL; gchar* classid_start; gchar* classid_end; gchar* classid_str; gchar* new_chunk; GncHTMLObjectCB h; object_tag = g_strstr_len( remainder_str, -1, "<object classid=" ); while (object_tag) { classid_start = object_tag + strlen( "<object classid=" ) + 1; classid_end = g_strstr_len( classid_start, -1, "\"" ); classid_str = g_strndup( classid_start, (classid_end - classid_start) ); end_object_tag = g_strstr_len( object_tag, -1, "</object>" ); if ( end_object_tag == NULL ) { /* Hmmm... no object end tag Return the original html string because we can't properly parse it */ g_free (classid_str); g_free (html_str_result); return g_strdup (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, classid_str ); 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\"", classid_str ); } html_str_start = html_str_result; new_chunk = g_strndup (remainder_str, (object_tag - remainder_str)); if (!html_str_start) html_str_result = g_strconcat (new_chunk, html_str_middle, NULL); else html_str_result = g_strconcat (html_str_start, new_chunk, html_str_middle, NULL); g_free( html_str_start ); g_free( new_chunk ); g_free( html_str_middle ); remainder_str = end_object_tag; object_tag = g_strstr_len( remainder_str, -1, "<object classid=" ); } if (html_str_result) { html_str_start = html_str_result; html_str_result = g_strconcat (html_str_start, remainder_str, NULL); g_free (html_str_start); } else html_str_result = g_strdup (remainder_str); return html_str_result; }
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); }