31 #include <glib/gi18n.h>
32 #include <glib/gstdio.h>
33 #include <sys/types.h>
46 #include "gnc-html-history.h"
52 static GHashTable * gnc_html_type_to_proto_hash = NULL;
53 GHashTable * gnc_html_proto_to_type_hash = NULL;
56 GHashTable* gnc_html_object_handlers = NULL;
59 GHashTable* gnc_html_stream_handlers = NULL;
62 GHashTable* gnc_html_url_handlers = NULL;
65 extern GHashTable* gnc_html_object_handlers;
67 G_DEFINE_ABSTRACT_TYPE(
GncHtml, gnc_html, GTK_TYPE_BIN)
70 static
void gnc_html_dispose( GObject* obj );
71 static
void gnc_html_finalize( GObject* obj );
74 #define GNC_HTML_GET_PRIVATE(o) (GNC_HTML(o)->priv)
76 #include "gnc-html-p.h"
81 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
83 gobject_class->dispose = gnc_html_dispose;
84 gobject_class->finalize = gnc_html_finalize;
86 klass->show_url = NULL;
87 klass->show_data = NULL;
89 klass->copy_to_clipboard = NULL;
90 klass->export_to_file = NULL;
93 klass->parse_url = NULL;
94 klass->set_parent = NULL;
103 priv->container = gtk_scrolled_window_new( NULL, NULL );
104 gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(priv->container),
105 GTK_POLICY_AUTOMATIC,
106 GTK_POLICY_AUTOMATIC );
107 priv->request_info = g_hash_table_new( g_str_hash, g_str_equal );
108 priv->history = gnc_html_history_new();
112 gnc_html_dispose( GObject* obj )
117 if ( priv->container != NULL )
119 gtk_widget_destroy( GTK_WIDGET(priv->container) );
120 g_object_unref( G_OBJECT(priv->container) );
121 priv->container = NULL;
123 if ( priv->request_info != NULL )
125 g_hash_table_destroy( priv->request_info );
126 priv->request_info = NULL;
128 if ( priv->history != NULL )
130 gnc_html_history_destroy( priv->history );
131 priv->history = NULL;
134 G_OBJECT_CLASS(gnc_html_parent_class)->dispose( obj );
138 gnc_html_finalize( GObject* obj )
142 if ( self->priv != NULL )
144 g_free( self->priv );
148 G_OBJECT_CLASS(gnc_html_parent_class)->finalize( obj );
154 extract_machine_name(
const gchar* path )
156 gchar machine_rexp[] =
"^(//[^/]*)/*(.*)?$";
159 gchar* machine = NULL;
161 if ( path == NULL )
return NULL;
163 regcomp( &compiled_m, machine_rexp, REG_EXTENDED );
167 if ( !regexec( &compiled_m, path, 4, match, 0 ) )
170 if ( match[1].rm_so != -1 )
172 machine = g_strndup( path + match[1].rm_so, match[1].rm_eo - match[1].rm_so );
175 regfree(&compiled_m);
186 gnc_html_parse_url(
GncHtml*
self,
const gchar* url,
187 gchar** url_location, gchar** url_label )
189 gchar uri_rexp[] =
"^(([^:][^:]+):)?([^#]+)?(#(.*))?$";
192 gchar* protocol = NULL;
195 gboolean found_protocol = FALSE;
196 gboolean found_path = FALSE;
197 gboolean found_label = FALSE;
201 g_return_val_if_fail(
self != NULL, NULL );
202 g_return_val_if_fail( GNC_IS_HTML(
self), NULL );
204 DEBUG(
"parsing %s, base_location %s",
205 url ? url :
"(null)",
206 self ? (priv->base_location ? priv->base_location
207 :
"(null base_location)")
210 regcomp( &compiled, uri_rexp, REG_EXTENDED );
212 if ( !regexec( &compiled, url, 6, match, 0 ) )
214 if ( match[2].rm_so != -1 )
216 protocol = g_new0( gchar, match[2].rm_eo - match[2].rm_so + 1 );
217 strncpy( protocol, url + match[2].rm_so, match[2].rm_eo - match[2].rm_so );
218 protocol[match[2].rm_eo - match[2].rm_so] = 0;
219 found_protocol = TRUE;
221 if ( match[3].rm_so != -1 )
223 path = g_new0( gchar, match[3].rm_eo - match[3].rm_so + 1 );
224 strncpy( path, url + match[3].rm_so, match[3].rm_eo - match[3].rm_so );
225 path[match[3].rm_eo - match[3].rm_so] = 0;
228 if ( match[5].rm_so != -1 )
230 label = g_new0( gchar, match[5].rm_eo - match[5].rm_so + 1 );
231 strncpy( label, url + match[5].rm_so, match[5].rm_eo - match[5].rm_so );
232 label[match[5].rm_eo - match[5].rm_so] = 0;
237 regfree( &compiled );
239 if ( found_protocol )
241 retval = g_hash_table_lookup( gnc_html_proto_to_type_hash, protocol );
242 if ( retval == NULL )
244 PWARN(
"unhandled URL type for '%s'", url ? url :
"(null)" );
245 retval = URL_TYPE_OTHER;
248 else if ( found_label && !found_path )
250 retval = URL_TYPE_JUMP;
256 retval = priv->base_type;
260 retval = URL_TYPE_FILE;
266 if ( !g_strcmp0( retval, URL_TYPE_FILE ) )
268 if ( !found_protocol && path &&
self && priv->base_location )
270 if ( g_path_is_absolute( path ) )
272 *url_location = g_strdup( path );
276 *url_location = g_build_filename( priv->base_location, path, (gchar*)NULL );
282 *url_location = g_strdup( path );
287 else if ( !g_strcmp0( retval, URL_TYPE_JUMP ) )
289 *url_location = NULL;
297 if ( !found_protocol && path &&
self && priv->base_location )
299 if ( g_path_is_absolute( path ) )
301 *url_location = g_build_filename( extract_machine_name( priv->base_location ),
302 path, (gchar*)NULL );
306 *url_location = g_build_filename( priv->base_location, path, (gchar*)NULL );
312 *url_location = g_strdup( path );
328 gnc_html_show_data(
GncHtml*
self,
const gchar* data,
int datalen )
330 g_return_if_fail(
self != NULL );
331 g_return_if_fail( GNC_IS_HTML(
self) );
333 if ( GNC_HTML_GET_CLASS(
self)->show_data != NULL )
335 GNC_HTML_GET_CLASS(
self)->show_data(
self, data, datalen );
339 DEBUG(
"'show_data' not implemented" );
353 gnc_html_show_url(
GncHtml*
self, URLType type,
354 const gchar* location,
const gchar* label,
355 gboolean new_window_hint )
357 URLType lc_type = NULL;
359 g_return_if_fail(
self != NULL );
360 g_return_if_fail( GNC_IS_HTML(
self) );
362 lc_type = g_ascii_strdown (type, -1);
363 if ( GNC_HTML_GET_CLASS(
self)->show_url != NULL )
365 GNC_HTML_GET_CLASS(
self)->show_url(
self, lc_type, location, label, new_window_hint );
369 DEBUG(
"'show_url' not implemented" );
382 gnc_html_reload(
GncHtml*
self )
384 g_return_if_fail(
self != NULL );
385 g_return_if_fail( GNC_IS_HTML(
self) );
387 if ( GNC_HTML_GET_CLASS(
self)->reload != NULL )
389 GNC_HTML_GET_CLASS(
self)->reload(
self );
393 DEBUG(
"'reload' not implemented" );
403 gnc_html_cancel(
GncHtml*
self )
405 g_return_if_fail(
self != NULL );
406 g_return_if_fail( GNC_IS_HTML(
self) );
408 if ( GNC_HTML_GET_CLASS(
self)->cancel != NULL )
410 GNC_HTML_GET_CLASS(
self)->cancel(
self );
414 DEBUG(
"'cancel' not implemented" );
425 gnc_html_destroy(
GncHtml*
self )
427 g_return_if_fail(
self != NULL );
428 g_return_if_fail( GNC_IS_HTML(
self) );
430 if ( g_object_is_floating( G_OBJECT(
self) ) )
432 (void)g_object_ref_sink( G_OBJECT(
self) );
435 g_object_unref( G_OBJECT(
self) );
439 gnc_html_set_urltype_cb(
GncHtml*
self, GncHTMLUrltypeCB urltype_cb )
443 g_return_if_fail(
self != NULL );
444 g_return_if_fail( GNC_IS_HTML(
self) );
446 priv = GNC_HTML_GET_PRIVATE(
self);
447 priv->urltype_cb = urltype_cb;
451 gnc_html_set_load_cb(
GncHtml*
self, GncHTMLLoadCB load_cb, gpointer data )
455 g_return_if_fail(
self != NULL );
456 g_return_if_fail( GNC_IS_HTML(
self) );
458 priv = GNC_HTML_GET_PRIVATE(
self);
459 priv->load_cb = load_cb;
460 priv->load_cb_data = data;
464 gnc_html_set_flyover_cb(
GncHtml*
self, GncHTMLFlyoverCB flyover_cb, gpointer data )
468 g_return_if_fail(
self != NULL );
469 g_return_if_fail( GNC_IS_HTML(
self) );
471 priv = GNC_HTML_GET_PRIVATE(
self);
472 priv->flyover_cb = flyover_cb;
473 priv->flyover_cb_data = data;
477 gnc_html_set_button_cb(
GncHtml*
self, GncHTMLButtonCB button_cb, gpointer data )
481 g_return_if_fail(
self != NULL );
482 g_return_if_fail( GNC_IS_HTML(
self) );
484 priv = GNC_HTML_GET_PRIVATE(
self);
485 priv->button_cb = button_cb;
486 priv->button_cb_data = data;
490 gnc_html_copy_to_clipboard(
GncHtml*
self )
492 g_return_if_fail(
self != NULL );
493 g_return_if_fail( GNC_IS_HTML(
self) );
495 if ( GNC_HTML_GET_CLASS(
self)->copy_to_clipboard != NULL )
497 GNC_HTML_GET_CLASS(
self)->copy_to_clipboard(
self );
501 DEBUG(
"'copy_to_clipboard' not implemented" );
510 gnc_html_export_to_file(
GncHtml*
self,
const gchar* filepath )
512 g_return_val_if_fail(
self != NULL, FALSE );
513 g_return_val_if_fail( GNC_IS_HTML(
self), FALSE );
515 if ( GNC_HTML_GET_CLASS(
self)->export_to_file != NULL )
517 return GNC_HTML_GET_CLASS(
self)->export_to_file(
self, filepath );
521 DEBUG(
"'export_to_file' not implemented" );
527 gnc_html_print(
GncHtml*
self,
const gchar* jobname, gboolean export_pdf )
529 g_return_if_fail(
self != NULL );
530 g_return_if_fail( GNC_IS_HTML(
self) );
532 if ( GNC_HTML_GET_CLASS(
self)->print != NULL )
534 GNC_HTML_GET_CLASS(
self)->print(
self, jobname, export_pdf );
538 DEBUG(
"'print' not implemented" );
543 gnc_html_get_history(
GncHtml*
self )
545 g_return_val_if_fail(
self != NULL, NULL );
546 g_return_val_if_fail( GNC_IS_HTML(
self), NULL );
548 return GNC_HTML_GET_PRIVATE(
self)->history;
553 gnc_html_get_widget(
GncHtml*
self )
555 g_return_val_if_fail(
self != NULL, NULL );
556 g_return_val_if_fail( GNC_IS_HTML(
self), NULL );
558 return GNC_HTML_GET_PRIVATE(
self)->container;
562 gnc_html_set_parent(
GncHtml*
self, GtkWindow* parent )
564 g_return_if_fail(
self != NULL );
565 g_return_if_fail( GNC_IS_HTML(
self) );
567 if ( GNC_HTML_GET_CLASS(
self)->set_parent != NULL )
569 GNC_HTML_GET_CLASS(
self)->set_parent(
self, parent );
573 DEBUG(
"'set_parent' not implemented" );
581 gnc_html_register_urltype( URLType type,
const char *protocol )
583 URLType lc_type = NULL;
584 char *lc_proto = NULL;
586 if (!gnc_html_type_to_proto_hash)
588 gnc_html_type_to_proto_hash = g_hash_table_new (g_str_hash, g_str_equal);
589 gnc_html_proto_to_type_hash = g_hash_table_new (g_str_hash, g_str_equal);
591 if (!protocol)
return FALSE;
593 lc_type = g_ascii_strdown (type, -1);
594 if (g_hash_table_lookup (gnc_html_type_to_proto_hash, lc_type))
600 lc_proto = g_ascii_strdown (protocol, -1);
601 g_hash_table_insert (gnc_html_type_to_proto_hash, lc_type, (gpointer)lc_proto);
603 g_hash_table_insert (gnc_html_proto_to_type_hash, (gpointer)lc_proto, lc_type);
609 gnc_html_initialize(
void )
618 { URL_TYPE_FILE,
"file" },
619 { URL_TYPE_JUMP,
"" },
620 { URL_TYPE_HTTP,
"http" },
621 { URL_TYPE_FTP,
"ftp" },
622 { URL_TYPE_SECURE,
"https" },
623 { URL_TYPE_REGISTER,
"gnc-register" },
624 { URL_TYPE_ACCTTREE,
"gnc-acct-tree" },
625 { URL_TYPE_REPORT,
"gnc-report" },
626 { URL_TYPE_OPTIONS,
"gnc-options" },
627 { URL_TYPE_SCHEME,
"gnc-scm" },
628 { URL_TYPE_HELP,
"gnc-help" },
629 { URL_TYPE_XMLDATA,
"gnc-xml" },
630 { URL_TYPE_PRICE,
"gnc-price" },
631 { URL_TYPE_BUDGET,
"gnc-budget" },
632 { URL_TYPE_OTHER,
"" },
636 for (i = 0; types[i].type; i++)
637 gnc_html_register_urltype (types[i].type, types[i].protocol);
649 gnc_build_url( URLType type,
const gchar* location,
const gchar* label )
651 URLType lc_type = NULL;
655 lc_type = g_ascii_strdown (type, -1);
656 type_name = g_hash_table_lookup (gnc_html_type_to_proto_hash, lc_type);
663 return g_strdup_printf(
"%s%s%s#%s", type_name, (*type_name ?
":" :
""),
664 (location ? location :
""),
669 return g_strdup_printf(
"%s%s%s", type_name, (*type_name ?
":" :
""),
670 (location ? location :
""));
685 gnc_html_encode_string(
const char * str)
687 static gchar *safe =
"$-._!*(),";
689 GString *encoded = g_string_new (
"");
690 gchar buffer[5], *ptr;
693 if (!str)
return NULL;
695 while (pos < strlen(str))
697 c = (
unsigned char) str[pos];
699 if ((( c >=
'A') && ( c <=
'Z')) ||
700 (( c >=
'a') && ( c <=
'z')) ||
701 (( c >=
'0') && ( c <=
'9')) ||
704 encoded = g_string_append_c (encoded, c);
708 encoded = g_string_append_c (encoded,
'+');
710 else if ( c ==
'\n' )
712 encoded = g_string_append (encoded,
"%0D%0A");
714 else if ( c !=
'\r' )
716 sprintf( buffer,
"%%%02X", (
int)c );
717 encoded = g_string_append (encoded, buffer);
724 g_string_free (encoded, FALSE);
731 gnc_html_decode_string(
const char * str)
733 static gchar * safe =
"$-._!*(),";
734 GString * decoded = g_string_new (
"");
740 if (!str)
return NULL;
744 c = (
unsigned char) * ptr;
745 if ((( c >=
'A') && ( c <=
'Z')) ||
746 (( c >=
'a') && ( c <=
'z')) ||
747 (( c >=
'0') && ( c <=
'9')) ||
750 decoded = g_string_append_c (decoded, c);
754 decoded = g_string_append_c (decoded,
' ');
756 else if (!strncmp(ptr,
"%0D0A", 5))
758 decoded = g_string_append (decoded,
"\n");
764 if (1 == sscanf(ptr,
"%02X", &hexval))
765 decoded = g_string_append_c(decoded, (
char)hexval);
767 decoded = g_string_append_c(decoded,
' ');
773 g_string_free (decoded, FALSE);
784 gnc_html_unescape_newlines(
const gchar * in)
786 const char * ip = in;
788 GString * rv = g_string_new(
"");
790 for (ip = in; *ip; ip++)
792 if ((*ip ==
'\\') && (*(ip + 1) ==
'n'))
794 g_string_append(rv,
"\n");
799 g_string_append_c(rv, *ip);
803 g_string_append_c(rv, 0);
805 g_string_free(rv, FALSE);
810 gnc_html_escape_newlines(
const gchar * in)
813 const char * ip = in;
814 GString * escaped = g_string_new(
"");
816 for (ip = in; *ip; ip++)
820 g_string_append(escaped,
"\\n");
824 g_string_append_c(escaped, *ip);
827 g_string_append_c(escaped, 0);
829 g_string_free(escaped, FALSE);
834 gnc_html_register_object_handler(
const char * classid,
835 GncHTMLObjectCB hand )
837 g_return_if_fail( classid != NULL );
839 if ( gnc_html_object_handlers == NULL )
841 gnc_html_object_handlers = g_hash_table_new( g_str_hash, g_str_equal );
844 gnc_html_unregister_object_handler( classid );
847 gchar *lc_id = g_ascii_strdown (classid, -1);
848 g_hash_table_insert( gnc_html_object_handlers, lc_id, hand );
853 gnc_html_unregister_object_handler(
const gchar* classid )
855 gchar* keyptr = NULL;
856 gchar* valptr = NULL;
857 gchar** p_keyptr = &keyptr;
858 gchar** p_valptr = &valptr;
859 gchar* lc_id = g_ascii_strdown (classid, -1);
861 if ( g_hash_table_lookup_extended( gnc_html_object_handlers,
863 (gpointer *)p_keyptr,
864 (gpointer *)p_valptr) )
866 g_hash_table_remove( gnc_html_object_handlers, lc_id );
873 gnc_html_register_stream_handler( URLType url_type, GncHTMLStreamCB hand )
875 g_return_if_fail( url_type != NULL && *url_type !=
'\0' );
877 if ( gnc_html_stream_handlers == NULL )
879 gnc_html_stream_handlers = g_hash_table_new( g_str_hash, g_str_equal );
882 gnc_html_unregister_stream_handler( url_type );
885 URLType lc_type = g_ascii_strdown (url_type, -1);
886 g_hash_table_insert( gnc_html_stream_handlers, lc_type, hand );
891 gnc_html_unregister_stream_handler( URLType url_type )
893 URLType lc_type = g_ascii_strdown (url_type, -1);
894 g_hash_table_remove( gnc_html_stream_handlers, lc_type );
899 gnc_html_register_url_handler( URLType url_type, GncHTMLUrlCB hand )
901 g_return_if_fail( url_type != NULL && *url_type !=
'\0' );
903 if ( gnc_html_url_handlers == NULL )
905 gnc_html_url_handlers = g_hash_table_new( g_str_hash, g_str_equal );
908 gnc_html_unregister_url_handler( url_type );
911 URLType lc_type = g_ascii_strdown (url_type, -1);
912 g_hash_table_insert( gnc_html_url_handlers, lc_type, hand );
917 gnc_html_unregister_url_handler( URLType url_type )
919 URLType lc_type = g_ascii_strdown (url_type, -1);
920 g_hash_table_remove( gnc_html_url_handlers, lc_type );
#define DEBUG(format, args...)
#define PWARN(format, args...)
Account handling public routines.
All type declarations for the whole Gnucash engine.
const gchar * QofLogModule