mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Bill Gribble's patch.
* summary: separate the HTML and HTTP processing functions into
different files to facilitate reuse. Modularize much of the
gnucash-specific behavior of the HTML code (<object> and form
submission) to use run-time-expandable bahavior tables. Add the
gnc-action: mechanism for installing form submission handlers.
* src/gnome/gng-gpg.c: initialize gnc-html handler for crypted
HTML objects. Remove all mention of GPG from gnc-html.c
* src/gnome/gnc-html-actions.c: new file. Add a simple form
submission action (action=gnc-action:gnc-info/form?CGI_URL) to
test submit and action processing. This is useless ATM. Some of
the stuff in the privacy comments is unimplemented yet.
* src/gnome/gnc-html-guppi.c: move all Guppi references from
gnc-html.c into a separate file, with an initializer for
the Guppi <object> tags.
* src/gnome/gnc-html.c: get rid of SSL references; all that stuff
is now in gnc-http.c. Restructure to use gnc-http instead of
ghttp directly. Finish GET and POST default handlers, and add
handler lookup/install mechanism for gnc-action: actions. crib
urlencoding function from gtkhtml guts.
* src/gnome/gnc-http.c: new file. Move HTTP stuff here. Finish
POST handling.
* src/gnome/top-level.c: add calls to Guppi, GPG, and gnc-html
init functions. These calls will eventually go into loadable
module startup functions, when we get loadable modules.
* src/scm/html-text.scm: Add html-markup/format.
(html-markup/format "%a %a %a %a" 1 2 3 4) does what you'd expect,
even if the non-format args are html-markup objects.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@3759 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
37
ChangeLog
37
ChangeLog
@@ -1,3 +1,40 @@
|
||||
2001-03-07 Bill Gribble <grib@billgribble.com>
|
||||
|
||||
* summary: separate the HTML and HTTP processing functions into
|
||||
different files to facilitate reuse. Modularize much of the
|
||||
gnucash-specific behavior of the HTML code (<object> and form
|
||||
submission) to use run-time-expandable bahavior tables. Add the
|
||||
gnc-action: mechanism for installing form submission handlers.
|
||||
|
||||
* src/gnome/gng-gpg.c: initialize gnc-html handler for crypted
|
||||
HTML objects. Remove all mention of GPG from gnc-html.c
|
||||
|
||||
* src/gnome/gnc-html-actions.c: new file. Add a simple form
|
||||
submission action (action=gnc-action:gnc-info/form?CGI_URL) to
|
||||
test submit and action processing. This is useless ATM. Some of
|
||||
the stuff in the privacy comments is unimplemented yet.
|
||||
|
||||
* src/gnome/gnc-html-guppi.c: move all Guppi references from
|
||||
gnc-html.c into a separate file, with an initializer for
|
||||
the Guppi <object> tags.
|
||||
|
||||
* src/gnome/gnc-html.c: get rid of SSL references; all that stuff
|
||||
is now in gnc-http.c. Restructure to use gnc-http instead of
|
||||
ghttp directly. Finish GET and POST default handlers, and add
|
||||
handler lookup/install mechanism for gnc-action: actions. crib
|
||||
urlencoding function from gtkhtml guts.
|
||||
|
||||
* src/gnome/gnc-http.c: new file. Move HTTP stuff here. Finish
|
||||
POST handling.
|
||||
|
||||
* src/gnome/top-level.c: add calls to Guppi, GPG, and gnc-html
|
||||
init functions. These calls will eventually go into loadable
|
||||
module startup functions, when we get loadable modules.
|
||||
|
||||
* src/scm/html-text.scm: Add html-markup/format.
|
||||
(html-markup/format "%a %a %a %a" 1 2 3 4) does what you'd expect,
|
||||
even if the non-format args are html-markup objects.
|
||||
|
||||
2001-03-07 Dave Peticolas <dave@krondo.com>
|
||||
|
||||
* src/gnome/top-level.c (gnc_ui_check_events): add timeout
|
||||
|
||||
@@ -34,9 +34,11 @@ libgncgnome_a_SOURCES = \
|
||||
gnc-datedelta.c \
|
||||
gnc-dateedit.c \
|
||||
gnc-gpg.c \
|
||||
gnc-html-embedded.c \
|
||||
gnc-html-actions.c \
|
||||
gnc-html-history.c \
|
||||
gnc-html-guppi.c \
|
||||
gnc-html.c \
|
||||
gnc-http.c \
|
||||
gnc-splash.c \
|
||||
gtkselect.c \
|
||||
mainwindow-account-tree.c \
|
||||
@@ -89,9 +91,11 @@ noinst_HEADERS = \
|
||||
gnc-datedelta.h \
|
||||
gnc-dateedit.h \
|
||||
gnc-gpg.h \
|
||||
gnc-html-embedded.h \
|
||||
gnc-html-actions.h \
|
||||
gnc-html-history.h \
|
||||
gnc-html-guppi.h \
|
||||
gnc-html.h \
|
||||
gnc-http.h \
|
||||
gnc-splash.h \
|
||||
gtkselect.h \
|
||||
mainwindow-account-tree.h \
|
||||
|
||||
@@ -23,13 +23,74 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if USE_GPG
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <gnome.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "gnc-html.h"
|
||||
#include "gnc-gpg.h"
|
||||
|
||||
static int handle_gpg_html(gnc_html * html, GtkHTMLEmbedded * eb, gpointer d);
|
||||
|
||||
/********************************************************************
|
||||
* gnc_gpg_init : called at startup time. adds a handler for crypted
|
||||
* HTML to gnc-html.
|
||||
********************************************************************/
|
||||
|
||||
void
|
||||
gnc_gpg_init(void) {
|
||||
gnc_html_register_object_handler("gnc-crypted-html", handle_gpg_html);
|
||||
}
|
||||
|
||||
static char *
|
||||
unescape_newlines(const gchar * in) {
|
||||
const char * ip = in;
|
||||
char * retval = g_strdup(in);
|
||||
char * op = retval;
|
||||
|
||||
for(ip=in; *ip; ip++) {
|
||||
if((*ip == '\\') && (*(ip+1)=='n')) {
|
||||
*op = '\012';
|
||||
op++;
|
||||
ip++;
|
||||
}
|
||||
else {
|
||||
*op = *ip;
|
||||
op++;
|
||||
}
|
||||
}
|
||||
*op = 0;
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* we just want to take the data and stuff it into the gnc-html
|
||||
* widget, blowing away the active streams. crypted-html contains a
|
||||
* complete HTML page. */
|
||||
static int
|
||||
handle_gpg_html(gnc_html * html, GtkHTMLEmbedded * eb, gpointer data) {
|
||||
int retval;
|
||||
char * cryptext = unescape_newlines(eb->data);
|
||||
char * cleartext = gnc_gpg_decrypt(cryptext, strlen(cryptext));
|
||||
GtkHTMLStream * handle;
|
||||
if(cleartext && cleartext[0]) {
|
||||
handle = gtk_html_begin(html);
|
||||
gtk_html_write(html, handle, cleartext, strlen(cleartext));
|
||||
gtk_html_end(html, handle, GTK_HTML_STREAM_OK);
|
||||
retval = TRUE;
|
||||
}
|
||||
else {
|
||||
retval = FALSE;
|
||||
}
|
||||
g_free(cleartext);
|
||||
g_free(cryptext);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
gnc_gpg_transform(const gchar * input, gint input_size,
|
||||
char ** gpg_argv) {
|
||||
@@ -206,3 +267,5 @@ gnc_gpg_make_keypair(const gchar * username,
|
||||
gnc_gpg_transform(stdin, strlen(stdin), argv);
|
||||
g_free(stdin);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -26,10 +26,11 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
char * gnc_gpg_encrypt(const gchar * cleartext, int cleartext_size,
|
||||
const gchar * recipient);
|
||||
char * gnc_gpg_decrypt(const gchar * cleartext, int cleartext_size);
|
||||
void gnc_gpg_make_keypair(const gchar * name, const gchar * id,
|
||||
const gchar * email);
|
||||
void gnc_gpg_init(void);
|
||||
char * gnc_gpg_encrypt(const gchar * cleartext, int cleartext_size,
|
||||
const gchar * recipient);
|
||||
char * gnc_gpg_decrypt(const gchar * cleartext, int cleartext_size);
|
||||
void gnc_gpg_make_keypair(const gchar * name, const gchar * id,
|
||||
const gchar * email);
|
||||
|
||||
#endif
|
||||
|
||||
134
src/gnome/gnc-html-actions.c
Normal file
134
src/gnome/gnc-html-actions.c
Normal file
@@ -0,0 +1,134 @@
|
||||
/********************************************************************
|
||||
* gnc-html-actions.c -- form submission actions *
|
||||
* Copyright (C) 2000 Bill Gribble <grib@billgribble.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 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
********************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* THIS IS PRIVACY-SENSITIVE CODE. The actions handled here are run
|
||||
* when gnucash needs to send HTML form information to a web server
|
||||
* and can modify the information being sent or send additional
|
||||
* information.
|
||||
*
|
||||
* Don't panic; all that means is that when an HTML form is loaded
|
||||
* into the Gnucash HTML browser, after the user clicks the "submit"
|
||||
* button, if the "action" in the form definition looks like
|
||||
* "gnc-action:ACTION-NAME?ACTION-ARGS", the action-name is used to
|
||||
* find a handler and the form is submitted by that handler. The
|
||||
* default action handlers allow Gnucash to send information about
|
||||
* itself along with a form, to send the form data in a GPG-encrypted
|
||||
* block, etc. This is useful functionality, but there are real
|
||||
* privacy concerns.
|
||||
*
|
||||
* Users: keep in mind that this is *not* a mechanism for executing
|
||||
* arbitrary code in your gnucash; the only "actions" that can be
|
||||
* taken must be compiled into the client, and you can disable them
|
||||
* globally with a Preferences option.
|
||||
*
|
||||
* Developers: Until we have a formally-codified privacy policy,
|
||||
* please follow these guidelines:
|
||||
*
|
||||
* 1. When actions send information that the user has not explicitly
|
||||
* entered, there should *always* be a dialog or other notification,
|
||||
* including the extra information to be sent, with an opportunity to
|
||||
* bail out.
|
||||
*
|
||||
* 2. Do not use a accept a complete URI to submit to as an argument
|
||||
* to actions. This might allow a malicious server to ask the
|
||||
* gnucash client for private information to be sent to itself, if
|
||||
* the user happened to go to that site from within the gnucash HTML
|
||||
* browser and click a form "SUBMIT" button. Submit only to servers
|
||||
* whose names the local user has specified as trusted servers for
|
||||
* gnucash-related actions.
|
||||
********************************************************************/
|
||||
|
||||
#include "config.h"
|
||||
#include <string.h>
|
||||
#include <glib.h>
|
||||
|
||||
#include "gnc-html-actions.h"
|
||||
#include "gnc-html.h"
|
||||
|
||||
static int handle_gnc_info_form_submit(gnc_html * html, const char * method,
|
||||
const char * action, const char * args,
|
||||
const char * encoding);
|
||||
|
||||
/********************************************************************
|
||||
* gnc_html_actions_init() : register the basic set of gnc-action:
|
||||
* form submission actions.
|
||||
********************************************************************/
|
||||
|
||||
void
|
||||
gnc_html_actions_init(void) {
|
||||
gnc_html_register_action_handler("gnc-info/form",
|
||||
handle_gnc_info_form_submit);
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* handle_gnc_info_form_submit() : submit the form arguments from
|
||||
* 'encoding', appending additional arguments describing the gnucash
|
||||
* client. this is justa test and doesn't submit any real
|
||||
* information.
|
||||
********************************************************************/
|
||||
|
||||
static int
|
||||
handle_gnc_info_form_submit(gnc_html * html, const char * method,
|
||||
const char * action, const char * args,
|
||||
const char * encoding) {
|
||||
char * extra_encoding = NULL;
|
||||
char * new_encoding = NULL;
|
||||
char * new_action = NULL;
|
||||
char * msg_1 = gnc_html_encode_string("gnucash version 1.5");
|
||||
char * msg_2 = gnc_html_encode_string("Hello, world");
|
||||
|
||||
if(!method || !action
|
||||
|| strcmp(action, "gnc-info/form")) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
extra_encoding = g_strconcat("gnc_version=", msg_1, "&"
|
||||
"gnc_message=", msg_2, NULL);
|
||||
|
||||
if(encoding) {
|
||||
new_encoding = g_strjoin("&", encoding, extra_encoding, NULL);
|
||||
}
|
||||
else {
|
||||
new_encoding = extra_encoding;
|
||||
extra_encoding = NULL;
|
||||
}
|
||||
|
||||
new_action = g_strconcat("http://localhost/", args, NULL);
|
||||
|
||||
if(!strcasecmp(method, "get")) {
|
||||
gnc_html_generic_get_submit(html, new_action, new_encoding);
|
||||
}
|
||||
else {
|
||||
gnc_html_generic_post_submit(html, new_action, new_encoding);
|
||||
}
|
||||
|
||||
g_free(extra_encoding);
|
||||
g_free(new_encoding);
|
||||
g_free(new_action);
|
||||
g_free(msg_1);
|
||||
g_free(msg_2);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
30
src/gnome/gnc-html-actions.h
Normal file
30
src/gnome/gnc-html-actions.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/********************************************************************
|
||||
* gnc-html-actions.h -- basic form submission actions *
|
||||
* Copyright (C) 2000 Bill Gribble <grib@billgribble.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 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
\********************************************************************/
|
||||
|
||||
#ifndef __GNC_HTML_ACTIONS_H__
|
||||
#define __GNC_HTML_ACTIONS_H__
|
||||
|
||||
#include "gnc-html.h"
|
||||
|
||||
void gnc_html_actions_init(void);
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/********************************************************************
|
||||
* gnc-html-embedded.c -- embed objects in the html stream. *
|
||||
* gnc-html-guppi.c -- embed guppi objects in the html stream. *
|
||||
* Copyright (C) 2000 Bill Gribble <grib@billgribble.com> *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
@@ -22,16 +22,96 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef USE_GUPPI
|
||||
|
||||
#include <gnome.h>
|
||||
#include <glib.h>
|
||||
#include <guile/gh.h>
|
||||
#include <gtkhtml/gtkhtml.h>
|
||||
#include <gtkhtml/gtkhtml-embedded.h>
|
||||
|
||||
#ifdef USE_GUPPI
|
||||
#include <libguppitank/guppi-tank.h>
|
||||
#endif
|
||||
#include "gnc-html.h"
|
||||
#include "gnc-html-guppi.h"
|
||||
|
||||
#include "gnc-html-embedded.h"
|
||||
#include "mainwindow-account-tree.h"
|
||||
static int handle_piechart(gnc_html * html, GtkHTMLEmbedded * eb, gpointer d);
|
||||
static int handle_barchart(gnc_html * html, GtkHTMLEmbedded * eb, gpointer d);
|
||||
static int handle_scatter(gnc_html * html, GtkHTMLEmbedded * eb, gpointer d);
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* gnc_html_guppi_init
|
||||
* add object handlers for guppi objects
|
||||
********************************************************************/
|
||||
|
||||
void
|
||||
gnc_html_guppi_init(void) {
|
||||
guppi_tank_init();
|
||||
gnc_html_register_object_handler("gnc-guppi-pie", handle_piechart);
|
||||
gnc_html_register_object_handler("gnc-guppi-bar", handle_barchart);
|
||||
gnc_html_register_object_handler("gnc-guppi-scatter", handle_scatter);
|
||||
}
|
||||
|
||||
/* the handlers for pie. bar, and scatter charts */
|
||||
static int
|
||||
handle_piechart(gnc_html * html, GtkHTMLEmbedded * eb, gpointer data) {
|
||||
GtkWidget * widg = NULL;
|
||||
int retval;
|
||||
widg = gnc_html_embedded_piechart(html, eb->width, eb->height,
|
||||
eb->params);
|
||||
if(widg) {
|
||||
gtk_widget_show_all(widg);
|
||||
gtk_container_add(GTK_CONTAINER(eb), widg);
|
||||
gtk_widget_set_usize(GTK_WIDGET(eb), eb->width, eb->height);
|
||||
retval = TRUE;
|
||||
}
|
||||
else {
|
||||
retval = FALSE;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_barchart(gnc_html * html, GtkHTMLEmbedded * eb, gpointer data) {
|
||||
GtkWidget * widg = NULL;
|
||||
int retval;
|
||||
widg = gnc_html_embedded_barchart(html, eb->width, eb->height,
|
||||
eb->params);
|
||||
if(widg) {
|
||||
gtk_widget_show_all(widg);
|
||||
gtk_container_add(GTK_CONTAINER(eb), widg);
|
||||
gtk_widget_set_usize(GTK_WIDGET(eb), eb->width, eb->height);
|
||||
retval = TRUE;
|
||||
}
|
||||
else {
|
||||
retval = FALSE;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_scatter(gnc_html * html, GtkHTMLEmbedded * eb, gpointer data) {
|
||||
GtkWidget * widg = NULL;
|
||||
int retval;
|
||||
widg = gnc_html_embedded_scatter(html, eb->width, eb->height,
|
||||
eb->params);
|
||||
if(widg) {
|
||||
gtk_widget_show_all(widg);
|
||||
gtk_container_add(GTK_CONTAINER(eb), widg);
|
||||
gtk_widget_set_usize(GTK_WIDGET(eb), eb->width, eb->height);
|
||||
retval = TRUE;
|
||||
}
|
||||
else {
|
||||
retval = FALSE;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* now we start the actual embedded object creation routines. well,
|
||||
* after some utilities.
|
||||
********************************************************************/
|
||||
|
||||
static double *
|
||||
read_doubles(const char * string, int nvalues) {
|
||||
@@ -102,8 +182,6 @@ free_strings(char ** strings, int nstrings) {
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_GUPPI
|
||||
|
||||
struct guppi_chart_data {
|
||||
GtkWidget * widget;
|
||||
GuppiObject * guppiobject;
|
||||
@@ -725,7 +803,6 @@ gnc_html_embedded_scatter(gnc_html * parent,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* USE_GUPPI */
|
||||
|
||||
/********************************************************************
|
||||
* gnc_html_embedded_account_tree
|
||||
@@ -751,26 +828,4 @@ set_bools(char * indices, gboolean * array, int num) {
|
||||
}
|
||||
|
||||
|
||||
GtkWidget *
|
||||
gnc_html_embedded_account_tree(gnc_html * parent,
|
||||
int w, int h, GHashTable * params) {
|
||||
AccountViewInfo info;
|
||||
GtkWidget * tree = gnc_mainwin_account_tree_new();
|
||||
char * param;
|
||||
int * fields;
|
||||
|
||||
memset(&info, 0, sizeof(AccountViewInfo));
|
||||
|
||||
if((param = g_hash_table_lookup(params, "fields"))) {
|
||||
set_bools(param, &(info.show_field[0]), NUM_ACCOUNT_FIELDS);
|
||||
}
|
||||
if((param = g_hash_table_lookup(params, "types"))) {
|
||||
set_bools(param, &(info.include_type[0]), NUM_ACCOUNT_TYPES);
|
||||
}
|
||||
gnc_mainwin_account_tree_set_view_info(GNC_MAINWIN_ACCOUNT_TREE(tree),
|
||||
info);
|
||||
|
||||
gnc_account_tree_refresh(GNC_ACCOUNT_TREE
|
||||
(GNC_MAINWIN_ACCOUNT_TREE(tree)->acc_tree));
|
||||
return tree;
|
||||
}
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/********************************************************************
|
||||
* gnc-html-embedded.h -- embed objects in the html stream *
|
||||
* gnc-html-guppi.h -- embed objects in the html stream *
|
||||
* Copyright (C) 2000 Bill Gribble <grib@billgribble.com> *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
@@ -20,12 +20,13 @@
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
\********************************************************************/
|
||||
|
||||
#ifndef __GNC_HTML_EMBEDDED_H__
|
||||
#define __GNC_HTML_EMBEDDED_H__
|
||||
#ifndef __GNC_HTML_GUPPI_H__
|
||||
#define __GNC_HTML_GUPPI_H__
|
||||
|
||||
#include <gnome.h>
|
||||
#include "gnc-html.h"
|
||||
|
||||
void gnc_html_guppi_init(void);
|
||||
GtkWidget * gnc_html_embedded_piechart(gnc_html * parent,
|
||||
gint w, gint h, GHashTable * params);
|
||||
GtkWidget * gnc_html_embedded_barchart(gnc_html * parent,
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gnc-html-history.h"
|
||||
|
||||
@@ -41,7 +42,7 @@ struct _gnc_html_history {
|
||||
********************************************************************/
|
||||
|
||||
gnc_html_history *
|
||||
gnc_html_history_new() {
|
||||
gnc_html_history_new(void) {
|
||||
gnc_html_history * hist = g_new0(gnc_html_history, 1);
|
||||
hist->nodes = NULL;
|
||||
hist->current_node = NULL;
|
||||
|
||||
@@ -32,16 +32,6 @@
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <ghttp_ssl.h>
|
||||
#endif
|
||||
|
||||
#include <ghttp.h>
|
||||
#include <gtkhtml/gtkhtml.h>
|
||||
#include <gtkhtml/gtkhtml-embedded.h>
|
||||
#ifdef USE_GUPPI
|
||||
@@ -64,29 +54,30 @@
|
||||
#include "gnc-engine-util.h"
|
||||
#include "gnc-gpg.h"
|
||||
#include "gnc-html.h"
|
||||
#include "gnc-html-actions.h"
|
||||
#include "gnc-http.h"
|
||||
#include "gnc-html-history.h"
|
||||
#include "gnc-html-embedded.h"
|
||||
#include "query-user.h"
|
||||
#include "window-help.h"
|
||||
#include "window-report.h"
|
||||
|
||||
struct _gnc_html {
|
||||
GtkWidget * container;
|
||||
GtkWidget * html;
|
||||
GtkWidget * container; /* parent of the gtkhtml widget */
|
||||
GtkWidget * html; /* gtkhtml widget itself */
|
||||
gchar * current_link; /* link under mouse pointer */
|
||||
|
||||
gchar * current_link; /* link under mouse pointer */
|
||||
URLType base_type; /* base of URL (path - filename) */
|
||||
gchar * base_location;
|
||||
|
||||
URLType base_type; /* base of URL (path - filename) */
|
||||
gchar * base_location;
|
||||
gnc_http * http; /* handles HTTP requests */
|
||||
GHashTable * request_info; /* hash uri to GList of GtkHTMLStream * */
|
||||
|
||||
/* callbacks */
|
||||
GncHTMLUrltypeCB urltype_cb;
|
||||
GncHTMLUrltypeCB urltype_cb; /* is this type OK for this instance? */
|
||||
GncHTMLLoadCB load_cb;
|
||||
GncHTMLFlyoverCB flyover_cb;
|
||||
GncHTMLButtonCB button_cb;
|
||||
|
||||
GList * requests; /* outstanding ghttp requests */
|
||||
|
||||
|
||||
gpointer flyover_cb_data;
|
||||
gpointer load_cb_data;
|
||||
gpointer button_cb_data;
|
||||
@@ -94,15 +85,18 @@ struct _gnc_html {
|
||||
struct _gnc_html_history * history;
|
||||
};
|
||||
|
||||
struct request_info {
|
||||
gchar * uri;
|
||||
ghttp_request * request;
|
||||
GtkHTMLStream * handle;
|
||||
};
|
||||
|
||||
/* This static indicates the debugging module that this .o belongs to. */
|
||||
/* indicates the debugging module that this .o belongs to. */
|
||||
static short module = MOD_HTML;
|
||||
|
||||
/* hashes an HTML <object classid="ID"> classid to a handler function */
|
||||
static GHashTable * gnc_html_object_handlers = NULL;
|
||||
|
||||
/* hashes an action name from a FORM definition to a handler function.
|
||||
* <form method=METHOD action=gnc-action:ACTION-NAME?ACTION-ARGS>
|
||||
* action-args is what gets passed to the handler. */
|
||||
static GHashTable * gnc_html_action_handlers = NULL;
|
||||
|
||||
static char error_404[] =
|
||||
"<html><body><h3>Not found</h3><p>The specified URL could not be loaded.</body></html>";
|
||||
|
||||
@@ -170,6 +164,9 @@ gnc_html_parse_url(gnc_html * html, const gchar * url,
|
||||
else if(!strcmp(protocol, "https")) {
|
||||
retval = URL_TYPE_SECURE;
|
||||
}
|
||||
else if(!strcmp(protocol, "gnc-action")) {
|
||||
retval = URL_TYPE_ACTION;
|
||||
}
|
||||
else if(!strcmp(protocol, "gnc-register")) {
|
||||
retval = URL_TYPE_REGISTER;
|
||||
}
|
||||
@@ -326,152 +323,100 @@ rebuild_url(URLType type, const gchar * location, const gchar * label) {
|
||||
}
|
||||
}
|
||||
|
||||
static guint ghttp_callback_tag = 0;
|
||||
static int ghttp_callback_enabled = FALSE;
|
||||
/************************************************************
|
||||
* gnc_html_http_request_cb: fires when an HTTP request is completed.
|
||||
* this is when it's time to load the data into the GtkHTML widget.
|
||||
************************************************************/
|
||||
|
||||
static gint
|
||||
ghttp_check_callback(gpointer data) {
|
||||
gnc_html * html = data;
|
||||
GList * current;
|
||||
ghttp_status status;
|
||||
struct request_info * req;
|
||||
URLType type;
|
||||
char * location = NULL;
|
||||
char * label = NULL;
|
||||
|
||||
/* walk the request list to deal with any complete requests */
|
||||
for(current = html->requests; current; current = current->next) {
|
||||
req = current->data;
|
||||
|
||||
status = ghttp_process(req->request);
|
||||
switch(status) {
|
||||
case ghttp_done:
|
||||
if (ghttp_get_body_len(req->request) > 0) {
|
||||
{
|
||||
/* hack alert FIXME:
|
||||
* This code tries to see if the returned body is
|
||||
* in fact gnc xml code. If it seems to be, then we
|
||||
* load it as data, rather than loading it into the
|
||||
* gtkhtml widget. My gut impression is that we should
|
||||
* probably be doing this somewhere else, some other
|
||||
* way, not here .... But I can't think of anything
|
||||
* better for now. -- linas
|
||||
*/
|
||||
const char * bufp = ghttp_get_body(req->request);
|
||||
bufp += strspn (bufp, " /t/v/f/n/r");
|
||||
if (!strncmp (bufp, "<?xml version", 13)) {
|
||||
gncFileOpenFile ((char *) req->uri);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
gtk_html_write(GTK_HTML(html->html),
|
||||
req->handle,
|
||||
ghttp_get_body(req->request),
|
||||
ghttp_get_body_len(req->request));
|
||||
gtk_html_end(GTK_HTML(html->html), req->handle, GTK_HTML_STREAM_OK);
|
||||
static void
|
||||
gnc_html_http_request_cb(const gchar * uri, int completed_ok,
|
||||
const gchar * body, gint body_len,
|
||||
gpointer user_data) {
|
||||
gnc_html * html = user_data;
|
||||
URLType type;
|
||||
char * location = NULL;
|
||||
char * label = NULL;
|
||||
GList * handles;
|
||||
GList * current;
|
||||
|
||||
type = gnc_html_parse_url(html, req->uri, &location, &label);
|
||||
handles = g_hash_table_lookup(html->request_info, uri);
|
||||
|
||||
/* handles will be NULL for an HTTP POST transaction, where we are
|
||||
* displaying the reply data. */
|
||||
if(!handles) {
|
||||
GtkHTMLStream * handle = gtk_html_begin(GTK_HTML(html->html));
|
||||
gtk_html_write(GTK_HTML(html->html), handle, body, body_len);
|
||||
gtk_html_end(GTK_HTML(html->html), handle, GTK_HTML_STREAM_OK);
|
||||
}
|
||||
/* otherwise, it's a normal SUBMIT transaction */
|
||||
else {
|
||||
for(current = handles; current; current = current->next) {
|
||||
/* request completed OK... write the HTML to the handles that
|
||||
* asked for that URI. */
|
||||
if(completed_ok) {
|
||||
gtk_html_write(GTK_HTML(html->html), (GtkHTMLStream *)(current->data),
|
||||
body, body_len);
|
||||
gtk_html_end(GTK_HTML(html->html), (GtkHTMLStream *)(current->data),
|
||||
GTK_HTML_STREAM_OK);
|
||||
type = gnc_html_parse_url(html, uri, &location, &label);
|
||||
if(label) {
|
||||
gtk_html_jump_to_anchor(GTK_HTML(html->html), label);
|
||||
}
|
||||
g_free(location);
|
||||
g_free(label);
|
||||
location = label = NULL;
|
||||
}
|
||||
/* request failed... body is the ghttp error text. */
|
||||
else {
|
||||
gtk_html_write(GTK_HTML(html->html), req->handle, error_404,
|
||||
strlen(error_404));
|
||||
gtk_html_end(GTK_HTML(html->html), req->handle, GTK_HTML_STREAM_ERROR);
|
||||
gtk_html_write(GTK_HTML(html->html), (GtkHTMLStream *)(current->data),
|
||||
error_start, strlen(error_start));
|
||||
gtk_html_write(GTK_HTML(html->html), (GtkHTMLStream *)(current->data),
|
||||
body, body_len);
|
||||
gtk_html_write(GTK_HTML(html->html), (GtkHTMLStream *)(current->data),
|
||||
error_end, strlen(error_end));
|
||||
gtk_html_end(GTK_HTML(html->html), (GtkHTMLStream *)(current->data),
|
||||
GTK_HTML_STREAM_ERROR);
|
||||
}
|
||||
ghttp_request_destroy(req->request);
|
||||
req->request = NULL;
|
||||
req->handle = NULL;
|
||||
current->data = NULL;
|
||||
g_free(req);
|
||||
break;
|
||||
|
||||
case ghttp_error:
|
||||
gtk_html_write(GTK_HTML(html->html), req->handle, error_start,
|
||||
strlen(error_start));
|
||||
gtk_html_write(GTK_HTML(html->html), req->handle,
|
||||
ghttp_get_error(req->request),
|
||||
strlen(ghttp_get_error(req->request)));
|
||||
gtk_html_write(GTK_HTML(html->html), req->handle, error_end,
|
||||
strlen(error_end));
|
||||
gtk_html_end(GTK_HTML(html->html), req->handle, GTK_HTML_STREAM_ERROR);
|
||||
ghttp_request_destroy(req->request);
|
||||
req->request = NULL;
|
||||
req->handle = NULL;
|
||||
current->data = NULL;
|
||||
g_free(req);
|
||||
break;
|
||||
|
||||
case ghttp_not_done:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* walk the list again to remove dead requests */
|
||||
current = html->requests;
|
||||
while(current) {
|
||||
if(current->data == NULL) {
|
||||
html->requests = g_list_remove_link(html->requests, current);
|
||||
current = html->requests;
|
||||
/* now clean up the request info from the hash table */
|
||||
handles = NULL;
|
||||
if(g_hash_table_lookup_extended(html->request_info, uri,
|
||||
(gpointer *)&location,
|
||||
(gpointer *)&handles)) {
|
||||
/* free the URI and the list of handles */
|
||||
g_free(location);
|
||||
g_list_free(handles);
|
||||
g_hash_table_remove(html->request_info, uri);
|
||||
}
|
||||
else {
|
||||
current = current->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* if all requests are done, disable the timeout */
|
||||
if(html->requests == NULL) {
|
||||
ghttp_callback_enabled = FALSE;
|
||||
ghttp_callback_tag = 0;
|
||||
return FALSE;
|
||||
}
|
||||
else {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
static int
|
||||
gnc_html_certificate_check_cb(ghttp_request * req, X509 * cert,
|
||||
void * user_data) {
|
||||
PINFO("checking SSL certificate...");
|
||||
X509_print_fp(stdout, cert);
|
||||
PINFO(" ... done\n");
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
/************************************************************
|
||||
* gnc_html_start_request: starts the gnc-http object working on an
|
||||
* http/https request.
|
||||
************************************************************/
|
||||
|
||||
static void
|
||||
gnc_html_start_request(gnc_html * html, gchar * uri, GtkHTMLStream * handle) {
|
||||
|
||||
struct request_info * info = g_new0(struct request_info, 1);
|
||||
GList * handles = NULL;
|
||||
gint need_request = FALSE;
|
||||
|
||||
info->request = ghttp_request_new();
|
||||
info->handle = handle;
|
||||
info->uri = g_strdup (uri);
|
||||
#ifdef HAVE_OPENSSL
|
||||
ghttp_enable_ssl(info->request);
|
||||
ghttp_set_ssl_certificate_callback(info->request,
|
||||
gnc_html_certificate_check_cb,
|
||||
(void *)html);
|
||||
#endif
|
||||
ghttp_set_uri(info->request, uri);
|
||||
ghttp_set_header(info->request, http_hdr_User_Agent,
|
||||
"gnucash/1.5 (Financial Browser for Linux; http://gnucash.org)");
|
||||
ghttp_set_sync(info->request, ghttp_async);
|
||||
ghttp_prepare(info->request);
|
||||
ghttp_process(info->request);
|
||||
/* we want to make a list of handles to fill with this URI.
|
||||
* multiple handles with the same URI will all get filled when the
|
||||
* request comes in. */
|
||||
handles = g_hash_table_lookup(html->request_info, uri);
|
||||
if(!handles) {
|
||||
need_request = TRUE;
|
||||
}
|
||||
|
||||
html->requests = g_list_append(html->requests, info);
|
||||
handles = g_list_append(handles, handle);
|
||||
g_hash_table_insert(html->request_info, uri, handles);
|
||||
|
||||
/* start the gtk timeout if not started */
|
||||
if(!ghttp_callback_enabled) {
|
||||
ghttp_callback_tag =
|
||||
gtk_timeout_add(100, ghttp_check_callback, (gpointer)html);
|
||||
ghttp_callback_enabled = TRUE;
|
||||
if(need_request) {
|
||||
gnc_http_start_request(html->http, uri, gnc_html_http_request_cb,
|
||||
(gpointer)html);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -633,27 +578,6 @@ gnc_html_guppi_redraw_cb(GtkHTMLEmbedded * eb,
|
||||
}
|
||||
#endif /* USE_GUPPI */
|
||||
|
||||
static char *
|
||||
unescape_newlines(const gchar * in) {
|
||||
const char * ip = in;
|
||||
char * retval = g_strdup(in);
|
||||
char * op = retval;
|
||||
|
||||
for(ip=in; *ip; ip++) {
|
||||
if((*ip == '\\') && (*(ip+1)=='n')) {
|
||||
*op = '\012';
|
||||
op++;
|
||||
ip++;
|
||||
}
|
||||
else {
|
||||
*op = *ip;
|
||||
op++;
|
||||
}
|
||||
}
|
||||
*op = 0;
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* gnc_html_object_requested_cb - called when an applet needs to be
|
||||
@@ -666,100 +590,17 @@ gnc_html_object_requested_cb(GtkHTML * html, GtkHTMLEmbedded * eb,
|
||||
GtkWidget * widg = NULL;
|
||||
gnc_html * gnchtml = data;
|
||||
int retval = FALSE;
|
||||
GncHTMLObjectCB h;
|
||||
|
||||
if(!strcmp(eb->classid, "gnc-guppi-pie")) {
|
||||
#ifdef USE_GUPPI
|
||||
widg = gnc_html_embedded_piechart(gnchtml, eb->width, eb->height,
|
||||
eb->params);
|
||||
#endif /* USE_GUPPI */
|
||||
if(widg) {
|
||||
gtk_widget_show_all(widg);
|
||||
gtk_container_add(GTK_CONTAINER(eb), widg);
|
||||
gtk_widget_set_usize(GTK_WIDGET(eb), eb->width, eb->height);
|
||||
retval = TRUE;
|
||||
}
|
||||
else {
|
||||
retval = FALSE;
|
||||
}
|
||||
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(gnchtml, eb, data);
|
||||
}
|
||||
else if(!strcmp(eb->classid, "gnc-guppi-bar")) {
|
||||
#ifdef USE_GUPPI
|
||||
widg = gnc_html_embedded_barchart(gnchtml, eb->width, eb->height,
|
||||
eb->params);
|
||||
#endif /* USE_GUPPI */
|
||||
if(widg) {
|
||||
gtk_widget_show_all(widg);
|
||||
gtk_container_add(GTK_CONTAINER(eb), widg);
|
||||
gtk_widget_set_usize(GTK_WIDGET(eb), eb->width, eb->height);
|
||||
retval = TRUE;
|
||||
}
|
||||
else {
|
||||
retval = FALSE;
|
||||
}
|
||||
else {
|
||||
return FALSE;
|
||||
}
|
||||
else if(!strcmp(eb->classid, "gnc-guppi-scatter")) {
|
||||
#ifdef USE_GUPPI
|
||||
widg = gnc_html_embedded_scatter(gnchtml, eb->width, eb->height,
|
||||
eb->params);
|
||||
#endif /* USE_GUPPI */
|
||||
if(widg) {
|
||||
gtk_widget_show_all(widg);
|
||||
gtk_container_add(GTK_CONTAINER(eb), widg);
|
||||
gtk_widget_set_usize(GTK_WIDGET(eb), eb->width, eb->height);
|
||||
retval = TRUE;
|
||||
}
|
||||
else {
|
||||
retval = FALSE;
|
||||
}
|
||||
}
|
||||
else if(!strcmp(eb->classid, "gnc-account-tree")) {
|
||||
widg = gnc_html_embedded_account_tree(gnchtml, eb->width, eb->height,
|
||||
eb->params);
|
||||
if(widg) {
|
||||
gtk_widget_show_all(widg);
|
||||
gtk_container_add(GTK_CONTAINER(eb), widg);
|
||||
gtk_widget_set_usize(GTK_WIDGET(eb), eb->width, eb->height);
|
||||
retval = TRUE;
|
||||
}
|
||||
else {
|
||||
retval = FALSE;
|
||||
}
|
||||
}
|
||||
#if USE_GPG
|
||||
else if(!strcmp(eb->classid, "gnc-crypted-html")) {
|
||||
/* we just want to take the data and stuff it into the widget,
|
||||
blowing away the active streams. crypted-html contains a
|
||||
complete HTML page. */
|
||||
char * cryptext = unescape_newlines(eb->data);
|
||||
char * cleartext = gnc_gpg_decrypt(cryptext, strlen(cryptext));
|
||||
GtkHTMLStream * handle;
|
||||
|
||||
if(cleartext && cleartext[0]) {
|
||||
handle = gtk_html_begin(html);
|
||||
gtk_html_write(html, handle, cleartext, strlen(cleartext));
|
||||
gtk_html_end(html, handle, GTK_HTML_STREAM_OK);
|
||||
retval = TRUE;
|
||||
}
|
||||
else {
|
||||
retval = FALSE;
|
||||
}
|
||||
g_free(cleartext);
|
||||
g_free(cryptext);
|
||||
}
|
||||
#endif /* USE_GPG */
|
||||
|
||||
#if 0 && defined(USE_GUPPI)
|
||||
if(widg) {
|
||||
gtk_signal_connect(GTK_OBJECT(eb), "draw_gdk",
|
||||
GTK_SIGNAL_FUNC(gnc_html_guppi_redraw_cb),
|
||||
widg);
|
||||
gtk_signal_connect(GTK_OBJECT(eb), "draw_print",
|
||||
GTK_SIGNAL_FUNC(gnc_html_guppi_print_cb),
|
||||
widg);
|
||||
}
|
||||
#endif
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
@@ -896,14 +737,41 @@ static int
|
||||
gnc_html_submit_cb(GtkHTML * html, const gchar * method,
|
||||
const gchar * action, const gchar * encoding,
|
||||
gpointer user_data) {
|
||||
if(!strcasecmp(method, "get")) {
|
||||
PINFO("GET submit: m='%s', a='%s', e='%s'",
|
||||
method, action, encoding);
|
||||
gnc_html * gnchtml = user_data;
|
||||
char * location = NULL;
|
||||
char * new_loc = NULL;
|
||||
char * label = NULL;
|
||||
char * submit_encoding = NULL;
|
||||
char ** action_parts;
|
||||
URLType type;
|
||||
GncHTMLActionCB cb;
|
||||
|
||||
type = gnc_html_parse_url(gnchtml, action, &location, &label);
|
||||
|
||||
if(type == URL_TYPE_ACTION) {
|
||||
if(gnc_html_action_handlers) {
|
||||
action_parts = g_strsplit(location, "?", 2);
|
||||
if(action_parts && action_parts[0]) {
|
||||
cb = g_hash_table_lookup(gnc_html_action_handlers, action_parts[0]);
|
||||
cb(gnchtml, method, action_parts[0], action_parts[1], encoding);
|
||||
}
|
||||
else {
|
||||
printf("tried to split on ? but failed...\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(!strcasecmp(method, "post")) {
|
||||
PINFO("POST submit: m='%s', a='%s', e='%s'",
|
||||
method, action, encoding);
|
||||
else {
|
||||
if(!strcasecmp(method, "get")) {
|
||||
gnc_html_generic_get_submit(gnchtml, action, encoding);
|
||||
}
|
||||
else if(!strcasecmp(method, "post")) {
|
||||
gnc_html_generic_post_submit(gnchtml, action, encoding);
|
||||
}
|
||||
}
|
||||
|
||||
g_free(location);
|
||||
g_free(label);
|
||||
g_free(new_loc);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -941,7 +809,7 @@ static void
|
||||
gnc_html_open_report(gnc_html * html, const gchar * location,
|
||||
const gchar * label, int newwin) {
|
||||
gnc_report_window * rwin;
|
||||
GtkHTMLStream * stream;
|
||||
GtkHTMLStream * handle;
|
||||
|
||||
/* make a new window if necessary */
|
||||
if(newwin) {
|
||||
@@ -957,8 +825,8 @@ gnc_html_open_report(gnc_html * html, const gchar * location,
|
||||
html->base_type = URL_TYPE_FILE;
|
||||
html->base_location = NULL;
|
||||
|
||||
stream = gtk_html_begin(GTK_HTML(html->html));
|
||||
gnc_html_load_to_stream(html, stream, URL_TYPE_REPORT, location, label);
|
||||
handle = gtk_html_begin(GTK_HTML(html->html));
|
||||
gnc_html_load_to_stream(html, handle, URL_TYPE_REPORT, location, label);
|
||||
}
|
||||
|
||||
|
||||
@@ -1006,7 +874,7 @@ void
|
||||
gnc_html_show_url(gnc_html * html, URLType type,
|
||||
const gchar * location, const gchar * label,
|
||||
int newwin_hint) {
|
||||
|
||||
|
||||
GtkHTMLStream * handle;
|
||||
int newwin;
|
||||
|
||||
@@ -1080,17 +948,17 @@ gnc_html_reload(gnc_html * html) {
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************\
|
||||
/********************************************************************
|
||||
* gnc_html_new
|
||||
* create and set up a new gtkhtml widget.
|
||||
\********************************************************************/
|
||||
********************************************************************/
|
||||
|
||||
gnc_html *
|
||||
gnc_html_new(void) {
|
||||
gnc_html * retval = g_new0(gnc_html, 1);
|
||||
|
||||
retval->container = gtk_scrolled_window_new(NULL, NULL);
|
||||
retval->html = gtk_html_new();
|
||||
retval->html = gtk_html_new();
|
||||
|
||||
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(retval->container),
|
||||
GTK_POLICY_AUTOMATIC,
|
||||
@@ -1098,8 +966,10 @@ gnc_html_new(void) {
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(retval->container),
|
||||
GTK_WIDGET(retval->html));
|
||||
|
||||
retval->history = gnc_html_history_new();
|
||||
|
||||
retval->request_info = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
retval->http = gnc_http_new();
|
||||
retval->history = gnc_html_history_new();
|
||||
|
||||
gtk_widget_ref (retval->container);
|
||||
gtk_object_sink (GTK_OBJECT (retval->container));
|
||||
@@ -1142,41 +1012,22 @@ gnc_html_new(void) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
|
||||
/********************************************************************
|
||||
* gnc_html_cancel
|
||||
* cancel any outstanding HTML fetch requests.
|
||||
\********************************************************************/
|
||||
********************************************************************/
|
||||
|
||||
void
|
||||
gnc_html_cancel(gnc_html * html) {
|
||||
GList * current;
|
||||
|
||||
if(ghttp_callback_enabled == TRUE) {
|
||||
gtk_timeout_remove(ghttp_callback_tag);
|
||||
ghttp_callback_enabled = FALSE;
|
||||
ghttp_callback_tag = 0;
|
||||
|
||||
/* go through and destroy all the requests */
|
||||
for(current = html->requests; current; current = current->next) {
|
||||
if(current->data) {
|
||||
struct request_info * r = current->data;
|
||||
ghttp_request_destroy(r->request);
|
||||
g_free(r->uri);
|
||||
g_free(r);
|
||||
current->data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* free the list backbone */
|
||||
g_list_free(html->requests);
|
||||
html->requests = NULL;
|
||||
}
|
||||
gnc_http_cancel_requests(html->http);
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************\
|
||||
/********************************************************************
|
||||
* gnc_html_destroy
|
||||
* destroy the struct
|
||||
\********************************************************************/
|
||||
********************************************************************/
|
||||
|
||||
void
|
||||
gnc_html_destroy(gnc_html * html) {
|
||||
@@ -1229,44 +1080,41 @@ gnc_html_set_button_cb(gnc_html * html, GncHTMLButtonCB button_cb,
|
||||
html->button_cb_data = data;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------- */
|
||||
/**************************************************************
|
||||
* gnc_html_export : wrapper around the builtin function in gtkhtml
|
||||
**************************************************************/
|
||||
|
||||
static gboolean
|
||||
raw_html_receiver (gpointer engine,
|
||||
const gchar *data,
|
||||
guint len,
|
||||
gpointer user_data)
|
||||
{
|
||||
const gchar *data,
|
||||
guint len,
|
||||
gpointer user_data) {
|
||||
FILE *fh = (FILE *) user_data;
|
||||
fwrite (data, len, 1, fh);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
gnc_html_export(gnc_html * html)
|
||||
{
|
||||
gnc_html_export(gnc_html * html) {
|
||||
const char *filepath;
|
||||
FILE *fh;
|
||||
|
||||
|
||||
filepath = fileBox (_("Save HTML To File"), NULL, NULL);
|
||||
PINFO (" user selected file=%s\n", filepath);
|
||||
fh = fopen (filepath, "w");
|
||||
if (NULL == fh)
|
||||
{
|
||||
const char *fmt = _("Could not open the file\n"
|
||||
" %s\n%s");
|
||||
char *buf = g_strdup_printf (fmt, filepath, strerror (errno));
|
||||
gnc_error_dialog (buf);
|
||||
if (buf) g_free (buf);
|
||||
return;
|
||||
if (NULL == fh) {
|
||||
const char *fmt = _("Could not open the file\n"
|
||||
" %s\n%s");
|
||||
char *buf = g_strdup_printf (fmt, filepath, strerror (errno));
|
||||
gnc_error_dialog (buf);
|
||||
if (buf) g_free (buf);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
gtk_html_save (GTK_HTML(html->html), raw_html_receiver, fh);
|
||||
fclose (fh);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------- */
|
||||
|
||||
void
|
||||
gnc_html_print(gnc_html * html) {
|
||||
PrintSession * ps = gnc_print_session_create();
|
||||
@@ -1290,29 +1138,197 @@ gnc_html_get_widget(gnc_html * html) {
|
||||
return html->container;
|
||||
}
|
||||
|
||||
|
||||
#ifdef _TEST_GNC_HTML_
|
||||
int
|
||||
main(int argc, char ** argv) {
|
||||
|
||||
GtkWidget * wind;
|
||||
gnc_html * html;
|
||||
|
||||
gnome_init("test", "1.0", argc, argv);
|
||||
gdk_rgb_init();
|
||||
gtk_widget_set_default_colormap (gdk_rgb_get_cmap ());
|
||||
gtk_widget_set_default_visual (gdk_rgb_get_visual ());
|
||||
|
||||
wind = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||
html = gnc_html_new();
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(wind), GTK_WIDGET(html->container));
|
||||
gtk_widget_show_all(wind);
|
||||
|
||||
gnc_html_load_file(html, "test.html");
|
||||
|
||||
gtk_main();
|
||||
|
||||
void
|
||||
gnc_html_register_object_handler(const char * classid,
|
||||
GncHTMLObjectCB hand) {
|
||||
if(!gnc_html_object_handlers) {
|
||||
gnc_html_object_handlers = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
}
|
||||
g_hash_table_insert(gnc_html_object_handlers, g_strdup(classid), hand);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
gnc_html_unregister_object_handler(const char * classid) {
|
||||
gchar * keyptr=NULL;
|
||||
gchar * valptr=NULL;
|
||||
|
||||
g_hash_table_lookup_extended(gnc_html_object_handlers,
|
||||
classid,
|
||||
(gpointer *)&keyptr,
|
||||
(gpointer *)&valptr);
|
||||
if(keyptr) {
|
||||
g_free(keyptr);
|
||||
g_hash_table_remove(gnc_html_object_handlers, classid);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gnc_html_register_action_handler(const char * actionid,
|
||||
GncHTMLActionCB hand) {
|
||||
if(!gnc_html_action_handlers) {
|
||||
gnc_html_action_handlers = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
}
|
||||
g_hash_table_insert(gnc_html_action_handlers, g_strdup(actionid), hand);
|
||||
}
|
||||
|
||||
void
|
||||
gnc_html_unregister_action_handler(const char * actionid) {
|
||||
gchar * keyptr=NULL;
|
||||
gchar * valptr=NULL;
|
||||
|
||||
g_hash_table_lookup_extended(gnc_html_action_handlers,
|
||||
actionid,
|
||||
(gpointer *)&keyptr,
|
||||
(gpointer *)&valptr);
|
||||
if(keyptr) {
|
||||
g_free(keyptr);
|
||||
g_hash_table_remove(gnc_html_action_handlers, actionid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* gnc_html_encode_string
|
||||
* RFC 1738 encoding of string for submission with an HTML form.
|
||||
* GPL code lifted from gtkhtml. copyright notice:
|
||||
*
|
||||
* Copyright (C) 1997 Martin Jones (mjones@kde.org)
|
||||
* Copyright (C) 1997 Torben Weis (weis@kde.org)
|
||||
* Copyright (C) 1999 Helix Code, Inc.
|
||||
********************************************************************/
|
||||
|
||||
char *
|
||||
gnc_html_encode_string(const char * str) {
|
||||
static gchar *safe = "$-._!*(),"; /* RFC 1738 */
|
||||
unsigned pos = 0;
|
||||
GString *encoded = g_string_new ("");
|
||||
gchar buffer[5], *ptr;
|
||||
guchar c;
|
||||
|
||||
while(pos < strlen(str)) {
|
||||
c = (unsigned char) str[pos];
|
||||
|
||||
if ((( c >= 'A') && ( c <= 'Z')) ||
|
||||
(( c >= 'a') && ( c <= 'z')) ||
|
||||
(( c >= '0') && ( c <= '9')) ||
|
||||
(strchr(safe, c))) {
|
||||
encoded = g_string_append_c (encoded, c);
|
||||
}
|
||||
else if ( c == ' ' ) {
|
||||
encoded = g_string_append_c (encoded, '+');
|
||||
}
|
||||
else if ( c == '\n' ) {
|
||||
encoded = g_string_append (encoded, "%0D%0A");
|
||||
}
|
||||
else if ( c != '\r' ) {
|
||||
sprintf( buffer, "%%%02X", (int)c );
|
||||
encoded = g_string_append (encoded, buffer);
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
|
||||
ptr = encoded->str;
|
||||
|
||||
g_string_free (encoded, FALSE);
|
||||
|
||||
return (char *)ptr;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* gnc_html_generic_get_submit() : normal 'get' submit method.
|
||||
********************************************************************/
|
||||
|
||||
void
|
||||
gnc_html_generic_get_submit(gnc_html * html, const char * action,
|
||||
const char * encoding) {
|
||||
URLType type;
|
||||
char * location = NULL;
|
||||
char * label = NULL;
|
||||
char * fullurl = NULL;
|
||||
|
||||
type = gnc_html_parse_url(html, action, &location, &label);
|
||||
fullurl = g_strconcat(location, "?", encoding, NULL);
|
||||
gnc_html_show_url(html, type, fullurl, label, 0);
|
||||
|
||||
g_free(location);
|
||||
g_free(label);
|
||||
g_free(fullurl);
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* gnc_html_generic_post_submit() : normal 'post' submit method.
|
||||
********************************************************************/
|
||||
|
||||
void
|
||||
gnc_html_generic_post_submit(gnc_html * html, const char * action,
|
||||
const char * encoding) {
|
||||
char * htmlstr = g_strconcat(encoding,
|
||||
"&submit=submit",
|
||||
NULL);
|
||||
gnc_http_start_post(html->http, action,
|
||||
"application/x-www-form-urlencoded",
|
||||
htmlstr, strlen(htmlstr),
|
||||
gnc_html_http_request_cb, html);
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* gnc_html_multipart_post_submit() : this is really sort of useless
|
||||
* but I'll make it better later. It's useless because FTMP CGI/php
|
||||
* don't properly decode the urlencoded values.
|
||||
********************************************************************/
|
||||
|
||||
void
|
||||
gnc_html_multipart_post_submit(gnc_html * html, const char * action,
|
||||
const char * encoding) {
|
||||
char * htmlstr = g_strdup("");
|
||||
char * next_htmlstr;
|
||||
char * next_pair = g_strconcat(encoding, "&submit=submit", NULL);
|
||||
char * name = NULL;
|
||||
char * value = NULL;
|
||||
char * extr_name = NULL;
|
||||
char * extr_value = NULL;
|
||||
char * length_line = NULL;
|
||||
|
||||
while(next_pair) {
|
||||
name = next_pair;
|
||||
if((value = strchr(name, '='))) {
|
||||
extr_name = g_strndup(name, value-name);
|
||||
next_pair = strchr(value, '&');
|
||||
if(next_pair) {
|
||||
extr_value = g_strndup(value+1, next_pair-value-1);
|
||||
next_pair++;
|
||||
}
|
||||
else {
|
||||
extr_value = g_strdup(value+1);
|
||||
}
|
||||
next_htmlstr =
|
||||
g_strconcat(htmlstr,
|
||||
"--XXXgncXXX\r\n",
|
||||
"Content-Disposition: form-data; name=\"",
|
||||
extr_name, "\"\r\n",
|
||||
"Content-Type: application/x-www-form-urlencoded\r\n\r\n",
|
||||
extr_value, "\r\n",
|
||||
NULL);
|
||||
|
||||
g_free(htmlstr);
|
||||
htmlstr = next_htmlstr;
|
||||
next_htmlstr = NULL;
|
||||
}
|
||||
else {
|
||||
next_pair = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
next_htmlstr = g_strconcat(htmlstr, "--XXXgncXXX--\r\n", NULL);
|
||||
g_free(htmlstr);
|
||||
htmlstr = next_htmlstr;
|
||||
next_htmlstr = NULL;
|
||||
gnc_http_start_post(html->http, action,
|
||||
"multipart/form-data; boundary=XXXgncXXX",
|
||||
htmlstr, strlen(htmlstr),
|
||||
gnc_html_http_request_cb, html);
|
||||
g_free(htmlstr);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/********************************************************************\
|
||||
* gnc-html.h -- display html with gnc special tags
|
||||
/********************************************************************
|
||||
* gnc-html.h -- display html with gnc special tags *
|
||||
* Copyright (C) 2000 Bill Gribble <grib@billgribble.com> *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
@@ -23,15 +23,10 @@
|
||||
#ifndef __GNC_HTML_H__
|
||||
#define __GNC_HTML_H__
|
||||
|
||||
#include <gnome.h>
|
||||
#include <ghttp.h>
|
||||
#include <glib.h>
|
||||
#include <gtkhtml/gtkhtml.h>
|
||||
|
||||
/*
|
||||
* The gnc_html_export() routine will export the html displayed to a
|
||||
* file. It will pop up a file dialog box to ask user for a
|
||||
* filename.
|
||||
*/
|
||||
#include <gdk/gdk.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
typedef enum { URL_TYPE_FILE, URL_TYPE_JUMP,
|
||||
URL_TYPE_HTTP, URL_TYPE_FTP,
|
||||
@@ -40,13 +35,15 @@ typedef enum { URL_TYPE_FILE, URL_TYPE_JUMP,
|
||||
URL_TYPE_REPORT, /* for gnucash report popups */
|
||||
URL_TYPE_SCHEME, /* for scheme code evaluation */
|
||||
URL_TYPE_HELP, /* for a gnucash help window */
|
||||
URL_TYPE_XMLDATA, /* links to gnucash XML data files */
|
||||
URL_TYPE_ACTION, /* for special SUBMIT actions */
|
||||
URL_TYPE_OTHER } URLType;
|
||||
|
||||
#include "gnc-html-history.h"
|
||||
|
||||
typedef struct _gnc_html gnc_html;
|
||||
|
||||
typedef int (*GncHTMLUrltypeCB)(URLType ut);
|
||||
typedef int (* GncHTMLUrltypeCB)(URLType ut);
|
||||
typedef void (* GncHTMLFlyoverCB)(gnc_html * html, const char * url,
|
||||
gpointer data);
|
||||
typedef void (* GncHTMLLoadCB)(gnc_html * html, URLType type,
|
||||
@@ -54,7 +51,11 @@ typedef void (* GncHTMLLoadCB)(gnc_html * html, URLType type,
|
||||
gpointer data);
|
||||
typedef int (* GncHTMLButtonCB)(gnc_html * html, GdkEventButton * event,
|
||||
gpointer data);
|
||||
|
||||
typedef int (* GncHTMLObjectCB)(gnc_html * html, GtkHTMLEmbedded * eb,
|
||||
gpointer data);
|
||||
typedef int (* GncHTMLActionCB)(gnc_html * html, const char * method,
|
||||
const char * action, const char * act_args,
|
||||
const char * encoding);
|
||||
gnc_html * gnc_html_new(void);
|
||||
void gnc_html_destroy(gnc_html * html);
|
||||
void gnc_html_show_url(gnc_html * html,
|
||||
@@ -65,9 +66,32 @@ void gnc_html_export(gnc_html * html);
|
||||
void gnc_html_print(gnc_html * html);
|
||||
void gnc_html_cancel(gnc_html * html);
|
||||
|
||||
URLType
|
||||
gnc_html_parse_url(gnc_html * html, const gchar * url,
|
||||
char ** url_location, char ** url_label);
|
||||
/* object handlers deal with <object classid="foo"> objects in HTML.
|
||||
* the handlers are looked up at object load time. */
|
||||
void gnc_html_register_object_handler(const char * classid,
|
||||
GncHTMLObjectCB hand);
|
||||
void gnc_html_unregister_object_handler(const char * classid);
|
||||
|
||||
/* action handlers deal with submitting forms of the type
|
||||
* <FORM action="gnc-action:action?args">. Normal get/post http:
|
||||
* forms are handled as would be expected, with no callback. */
|
||||
void gnc_html_register_action_handler(const char * action,
|
||||
GncHTMLActionCB hand);
|
||||
void gnc_html_unregister_action_handler(const char * action);
|
||||
|
||||
/* default action handlers for GET and POST methods. 'generic_post'
|
||||
* is the trivial application/x-www-form-urlencoded submit,
|
||||
* multipart-post is a multipart/form-data submit. */
|
||||
void gnc_html_generic_get_submit(gnc_html * html, const char * act,
|
||||
const char * encoding);
|
||||
void gnc_html_generic_post_submit(gnc_html * html, const char * act,
|
||||
const char * encoding);
|
||||
void gnc_html_multipart_post_submit(gnc_html * html, const char * a,
|
||||
const char * encoding);
|
||||
|
||||
URLType gnc_html_parse_url(gnc_html * html, const gchar * url,
|
||||
char ** url_location, char ** url_label);
|
||||
char * gnc_html_encode_string(const char * in);
|
||||
|
||||
gnc_html_history * gnc_html_get_history(gnc_html * html);
|
||||
GtkWidget * gnc_html_get_widget(gnc_html * html);
|
||||
|
||||
249
src/gnome/gnc-http.c
Normal file
249
src/gnome/gnc-http.c
Normal file
@@ -0,0 +1,249 @@
|
||||
/********************************************************************
|
||||
* gnc-http.c -- handle processing of HTTP requests via gnome-http *
|
||||
* Copyright (C) 2001 Bill Gribble <grib@billgribble.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 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
********************************************************************/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <ghttp_ssl.h>
|
||||
#endif
|
||||
|
||||
#include <ghttp.h>
|
||||
#include <glib.h>
|
||||
#include <gtk/gtkmain.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gnc-http.h"
|
||||
|
||||
struct _gnc_http {
|
||||
GList * requests;
|
||||
guint callback_tag;
|
||||
gint callback_enabled;
|
||||
};
|
||||
|
||||
struct request_info {
|
||||
gchar * uri;
|
||||
ghttp_request * request;
|
||||
GncHTTPRequestCB callback;
|
||||
gpointer callback_data;
|
||||
};
|
||||
|
||||
gnc_http *
|
||||
gnc_http_new(void) {
|
||||
gnc_http * ret = g_new0(struct _gnc_http, 1);
|
||||
ret->requests = NULL;
|
||||
ret->callback_tag = 0;
|
||||
ret->callback_enabled = FALSE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
gnc_http_destroy(gnc_http * http) {
|
||||
gnc_http_cancel_requests(http);
|
||||
g_free(http);
|
||||
}
|
||||
|
||||
void
|
||||
gnc_http_cancel_requests(gnc_http * http) {
|
||||
GList * current;
|
||||
|
||||
if(http->callback_enabled == TRUE) {
|
||||
/* FIXME : should replace this with glib idle function -- bg */
|
||||
gtk_timeout_remove(http->callback_tag);
|
||||
http->callback_enabled = FALSE;
|
||||
http->callback_tag = 0;
|
||||
|
||||
/* go through and destroy all the requests */
|
||||
for(current = http->requests; current; current = current->next) {
|
||||
if(current->data) {
|
||||
struct request_info * r = current->data;
|
||||
ghttp_request_destroy(r->request);
|
||||
g_free(r->uri);
|
||||
g_free(r);
|
||||
current->data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* free the list backbone */
|
||||
g_list_free(http->requests);
|
||||
http->requests = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static gint
|
||||
ghttp_check_callback(gpointer data) {
|
||||
gnc_http * http = data;
|
||||
GList * current;
|
||||
ghttp_status status;
|
||||
struct request_info * req;
|
||||
|
||||
/* walk the request list to deal with any complete requests */
|
||||
for(current = http->requests; current; current = current->next) {
|
||||
req = current->data;
|
||||
|
||||
status = ghttp_process(req->request);
|
||||
switch(status) {
|
||||
case ghttp_done:
|
||||
if(req->callback) {
|
||||
(req->callback)(req->uri, TRUE,
|
||||
ghttp_get_body(req->request),
|
||||
ghttp_get_body_len(req->request),
|
||||
req->callback_data);
|
||||
}
|
||||
ghttp_request_destroy(req->request);
|
||||
req->request = NULL;
|
||||
current->data = NULL;
|
||||
g_free(req);
|
||||
break;
|
||||
|
||||
case ghttp_error:
|
||||
if(req->callback) {
|
||||
(req->callback)(req->uri, FALSE,
|
||||
ghttp_get_error(req->request),
|
||||
strlen(ghttp_get_error(req->request)),
|
||||
req->callback_data);
|
||||
}
|
||||
ghttp_request_destroy(req->request);
|
||||
req->request = NULL;
|
||||
current->data = NULL;
|
||||
g_free(req);
|
||||
break;
|
||||
|
||||
case ghttp_not_done:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* walk the list again to remove dead requests */
|
||||
current = http->requests;
|
||||
while(current) {
|
||||
if(current->data == NULL) {
|
||||
http->requests = g_list_remove_link(http->requests, current);
|
||||
current = http->requests;
|
||||
}
|
||||
else {
|
||||
current = current->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* if all requests are done, disable the timeout */
|
||||
if(http->requests == NULL) {
|
||||
http->callback_enabled = FALSE;
|
||||
http->callback_tag = 0;
|
||||
return FALSE;
|
||||
}
|
||||
else {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
static int
|
||||
gnc_http_certificate_check_cb(ghttp_request * req, X509 * cert,
|
||||
void * user_data) {
|
||||
PINFO("checking SSL certificate...");
|
||||
X509_print_fp(stdout, cert);
|
||||
PINFO(" ... done\n");
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
gnc_http_start_request(gnc_http * http, const gchar * uri,
|
||||
GncHTTPRequestCB cb, gpointer user_data) {
|
||||
|
||||
struct request_info * info = g_new0(struct request_info, 1);
|
||||
|
||||
info->request = ghttp_request_new();
|
||||
info->uri = g_strdup (uri);
|
||||
info->callback = cb;
|
||||
info->callback_data = user_data;
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
ghttp_enable_ssl(info->request);
|
||||
ghttp_set_ssl_certificate_callback(info->request,
|
||||
gnc_http_certificate_check_cb,
|
||||
(void *)http);
|
||||
#endif
|
||||
ghttp_set_uri(info->request, (char *)uri);
|
||||
ghttp_set_header(info->request, http_hdr_User_Agent,
|
||||
"gnucash/1.5 (Financial Browser for Linux; http://gnucash.org)");
|
||||
ghttp_set_sync(info->request, ghttp_async);
|
||||
ghttp_set_type(info->request, ghttp_type_get);
|
||||
ghttp_prepare(info->request);
|
||||
ghttp_process(info->request);
|
||||
|
||||
http->requests = g_list_append(http->requests, info);
|
||||
|
||||
/* start the gtk timeout if not started */
|
||||
/* FIXME : should replace this with glib idle function -- bg */
|
||||
if(!http->callback_enabled) {
|
||||
|
||||
http->callback_tag =
|
||||
gtk_timeout_add(100, ghttp_check_callback, (gpointer)http);
|
||||
http->callback_enabled = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gnc_http_start_post(gnc_http * http, const char * uri,
|
||||
const char * content_type,
|
||||
const char * data, int datalen,
|
||||
GncHTTPRequestCB cb, gpointer user_data) {
|
||||
struct request_info * info = g_new0(struct request_info, 1);
|
||||
|
||||
info->request = ghttp_request_new();
|
||||
info->uri = g_strdup (uri);
|
||||
info->callback = cb;
|
||||
info->callback_data = user_data;
|
||||
#ifdef HAVE_OPENSSL
|
||||
ghttp_enable_ssl(info->request);
|
||||
ghttp_set_ssl_certificate_callback(info->request,
|
||||
gnc_http_certificate_check_cb,
|
||||
(void *)http);
|
||||
#endif
|
||||
ghttp_set_uri(info->request, uri);
|
||||
ghttp_set_header(info->request, http_hdr_User_Agent,
|
||||
"gnucash/1.5 (Financial Browser for Linux; http://gnucash.org)");
|
||||
ghttp_set_header(info->request, http_hdr_Content_Type, content_type);
|
||||
ghttp_set_sync(info->request, ghttp_async);
|
||||
ghttp_set_type(info->request, ghttp_type_post);
|
||||
ghttp_set_body(info->request, data, datalen);
|
||||
|
||||
ghttp_prepare(info->request);
|
||||
ghttp_process(info->request);
|
||||
|
||||
http->requests = g_list_append(http->requests, info);
|
||||
|
||||
/* start the gtk timeout if not started */
|
||||
if(!http->callback_enabled) {
|
||||
http->callback_tag =
|
||||
gtk_timeout_add(100, ghttp_check_callback, (gpointer)http);
|
||||
http->callback_enabled = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
43
src/gnome/gnc-http.h
Normal file
43
src/gnome/gnc-http.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/********************************************************************
|
||||
* gnc-http.h -- handle HTTP requests. thin wrapper on gnome-http. *
|
||||
* Copyright (C) 2001 Bill Gribble <grib@billgribble.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 *
|
||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
||||
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
||||
********************************************************************/
|
||||
|
||||
#ifndef __GNC_HTTP_H__
|
||||
#define __GNC_HTTP_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
typedef struct _gnc_http gnc_http;
|
||||
|
||||
typedef void (* GncHTTPRequestCB)(const char * uri, int completed_ok,
|
||||
const char * body, int body_len,
|
||||
gpointer user_data);
|
||||
gnc_http * gnc_http_new(void);
|
||||
void gnc_http_destroy(gnc_http * html);
|
||||
void gnc_http_start_request(gnc_http * http, const char * uri,
|
||||
GncHTTPRequestCB cb, gpointer user_data);
|
||||
void gnc_http_start_post(gnc_http * http, const char * uri,
|
||||
const char * content_type,
|
||||
const char * body, int body_len,
|
||||
GncHTTPRequestCB cb, gpointer user_data);
|
||||
void gnc_http_cancel_requests(gnc_http * http);
|
||||
|
||||
#endif
|
||||
@@ -25,11 +25,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <gnome.h>
|
||||
#include <gtkhtml/gtkhtml.h>
|
||||
#include <guile/gh.h>
|
||||
#ifdef USE_GUPPI
|
||||
#include <libguppitank/guppi-tank.h>
|
||||
#endif
|
||||
#include <popt.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -50,6 +46,13 @@
|
||||
#include "gnc-component-manager.h"
|
||||
#include "gnc-engine-util.h"
|
||||
#include "gnc-splash.h"
|
||||
#include "gnc-html-actions.h"
|
||||
#ifdef USE_GUPPI
|
||||
#include "gnc-html-guppi.h"
|
||||
#endif
|
||||
#ifdef USE_GPG
|
||||
#include "gnc-gpg.h"
|
||||
#endif
|
||||
#include "gnc-ui.h"
|
||||
#include "gnc.h"
|
||||
#include "gnucash-color.h"
|
||||
@@ -212,9 +215,15 @@ gnucash_ui_init(void)
|
||||
gtk_widget_set_default_colormap (gdk_rgb_get_cmap ());
|
||||
gtk_widget_set_default_visual (gdk_rgb_get_visual ());
|
||||
|
||||
/* load default HTML action handlers */
|
||||
gnc_html_actions_init();
|
||||
#ifdef USE_GUPPI
|
||||
/* initialize guppi */
|
||||
guppi_tank_init();
|
||||
/* initialize guppi handling in gnc-html */
|
||||
gnc_html_guppi_init();
|
||||
#endif
|
||||
#ifdef USE_GPG
|
||||
/* initialize gpg handling in gnc-html */
|
||||
gnc_gpg_init();
|
||||
#endif
|
||||
|
||||
/* put up splash screen */
|
||||
|
||||
@@ -655,9 +655,22 @@ gnc_help_window_new (void) {
|
||||
|
||||
void
|
||||
gnc_help_window_destroy(gnc_help_window * help) {
|
||||
|
||||
if (!help) return;
|
||||
|
||||
gnc_unregister_gui_component_by_data (WINDOW_HELP_CM_CLASS, help);
|
||||
|
||||
gtk_signal_disconnect_by_func(GTK_OBJECT(help->toplevel),
|
||||
GTK_SIGNAL_FUNC(gnc_help_window_destroy_cb),
|
||||
(gpointer)help);
|
||||
/* close the help index db */
|
||||
if(help->index_db) {
|
||||
help->index_db->close(help->index_db);
|
||||
}
|
||||
|
||||
/* take care of the gnc-html object specially */
|
||||
gtk_widget_ref(gnc_html_get_widget(help->html));
|
||||
gnc_html_destroy(help->html);
|
||||
|
||||
gtk_widget_destroy(GTK_WIDGET(help->toplevel));
|
||||
}
|
||||
|
||||
|
||||
@@ -118,6 +118,34 @@
|
||||
#f
|
||||
entities)))
|
||||
|
||||
;; I'm not entirely pleased about the way this works, but I can't
|
||||
;; really see a way around it. It still works within the style
|
||||
;; system, but it flattens out its children's lists prematurely. Has
|
||||
;; to, to pass them as args to sprintf.
|
||||
|
||||
(define (gnc:html-markup/format format . entities)
|
||||
(lambda (doc)
|
||||
(apply
|
||||
sprintf #f format
|
||||
(map
|
||||
(lambda (elt)
|
||||
(let ((rendered-elt
|
||||
(cond ((procedure? elt)
|
||||
(elt doc))
|
||||
((gnc:html-object? elt)
|
||||
(gnc:html-object-render elt doc))
|
||||
(#t
|
||||
(gnc:html-document-render-data doc elt)))))
|
||||
(cond
|
||||
((string? rendered-elt)
|
||||
rendered-elt)
|
||||
((list? rendered-elt)
|
||||
(apply string-append (gnc:report-tree-collapse rendered-elt)))
|
||||
(#t
|
||||
(simple-format "hold on there podner. form='~s'\n" rendered-elt)
|
||||
""))))
|
||||
entities))))
|
||||
|
||||
(define (gnc:html-markup-p . rest)
|
||||
(apply gnc:html-markup "p" rest))
|
||||
|
||||
@@ -182,9 +210,10 @@
|
||||
(gnc:html-document-push-style doc (gnc:html-text-style p))
|
||||
(for-each-in-order
|
||||
(lambda (elt)
|
||||
(if (procedure? elt)
|
||||
(push (elt doc))
|
||||
(push (gnc:html-document-render-data doc elt))))
|
||||
(cond ((procedure? elt)
|
||||
(push (elt doc)))
|
||||
(#t
|
||||
(push (gnc:html-document-render-data doc elt)))))
|
||||
(gnc:html-text-body p))
|
||||
(gnc:html-document-pop-style doc)
|
||||
(gnc:html-style-table-uncompile (gnc:html-text-style p))
|
||||
@@ -195,10 +224,11 @@
|
||||
(push (lambda (l) (set! retval (cons l retval)))))
|
||||
(push (gnc:html-document-markup-start doc markup attrib))
|
||||
(for-each-in-order
|
||||
(lambda (elt)
|
||||
(if (procedure? elt)
|
||||
(push (elt doc))
|
||||
(push (gnc:html-document-render-data doc elt))))
|
||||
(lambda (elt)
|
||||
(cond ((procedure? elt)
|
||||
(push (elt doc)))
|
||||
(#t
|
||||
(push (gnc:html-document-render-data doc elt)))))
|
||||
entities)
|
||||
(if end-tag?
|
||||
(push (gnc:html-document-markup-end doc markup)))
|
||||
|
||||
@@ -357,16 +357,19 @@ new, totally cool report, consult the mailing list ")
|
||||
(gnc:html-markup-b date-string2) ".")
|
||||
|
||||
(gnc:html-markup-p
|
||||
(_ "The relative date option is ")
|
||||
(gnc:html-markup-b rel-date-string) ".")
|
||||
(gnc:html-markup/format
|
||||
(_ "The relative date option is %a.")
|
||||
(gnc:html-markup-b rel-date-string)))
|
||||
|
||||
(gnc:html-markup-p
|
||||
(_ "The combination date option is ")
|
||||
(gnc:html-markup-b combo-date-string) ".")
|
||||
(gnc:html-markup/format
|
||||
(_ "The combination date option is %a.")
|
||||
(gnc:html-markup-b combo-date-string)))
|
||||
|
||||
(gnc:html-markup-p
|
||||
(_ "The number option is ")
|
||||
(gnc:html-markup-b (number->string num-val)) ".")
|
||||
(gnc:html-markup/format
|
||||
(_ "The number option is %a.")
|
||||
(gnc:html-markup-b (number->string num-val))))
|
||||
|
||||
;; Here we print the value of the number option formatted as
|
||||
;; currency. When printing currency values, you should use
|
||||
@@ -375,10 +378,11 @@ new, totally cool report, consult the mailing list ")
|
||||
;; appropriately in the current locale. Don't try to format
|
||||
;; it yourself -- it will be wrong in other locales.
|
||||
(gnc:html-markup-p
|
||||
(_ "The number option formatted as currency is ")
|
||||
(gnc:html-markup-b
|
||||
(gnc:amount->string num-val (gnc:default-print-info #f))))))
|
||||
|
||||
(gnc:html-markup/format
|
||||
(_ "The number option formatted as currency is %a.")
|
||||
(gnc:html-markup-b
|
||||
(gnc:amount->string num-val (gnc:default-print-info #f)))))))
|
||||
|
||||
;; you can add as many objects as you want. Here's another
|
||||
;; one. We'll make a single-column table of the selected list
|
||||
;; options just for grins.
|
||||
|
||||
Reference in New Issue
Block a user