mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Bill Gribble's patch.
* gnc-network.{c,h}: new files. Functions for user registration and authentication. * gnc-gpg.c: fix bugs. make gpg operations optionally asynchronous via gdk_input_add(). * gnc-html.c: fix URL base name handling. Rework processing of http requests. * gnc-http.c: memory management in gnome_http. Still some memory leaks in there, I think. * gnc-html-actions.{c,h}: remove files. Content moved into gnc-network. * prefs.scm: Add hidden preference for GnuCash Network user ID. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@3814 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
6a7acc416d
commit
034eb6859b
23
ChangeLog
23
ChangeLog
@ -1,3 +1,26 @@
|
||||
2001-03-21 Dave Peticolas <dave@krondo.com>
|
||||
|
||||
* configure.in: take out --enable-gpg argument, is run-time dep
|
||||
|
||||
2001-03-21 Bill Gribble <grib@billgribble.com>
|
||||
|
||||
* gnc-network.{c,h}: new files. Functions for user registration
|
||||
and authentication.
|
||||
|
||||
* gnc-gpg.c: fix bugs. make gpg operations optionally
|
||||
asynchronous via gdk_input_add().
|
||||
|
||||
* gnc-html.c: fix URL base name handling. Rework processing of
|
||||
http requests.
|
||||
|
||||
* gnc-http.c: memory management in gnome_http. Still some
|
||||
memory leaks in there, I think.
|
||||
|
||||
* gnc-html-actions.{c,h}: remove files. Content moved into
|
||||
gnc-network.
|
||||
|
||||
* prefs.scm: Add hidden preference for GnuCash Network user ID.
|
||||
|
||||
2001-03-21 Dave Peticolas <dave@krondo.com>
|
||||
|
||||
* src/scm/report-utilities.scm
|
||||
|
@ -73,9 +73,6 @@
|
||||
#undef HAVE_LIBGHTTP
|
||||
#undef HAVE_OPENSSL
|
||||
|
||||
/* GPG support. This is an --enable option */
|
||||
#undef USE_GPG
|
||||
|
||||
/* misc image and compression libs needed by html widget */
|
||||
#undef HAVE_ZLIB
|
||||
#undef HAVE_PNG
|
||||
|
@ -155,13 +155,6 @@ AC_ARG_ENABLE( profile,
|
||||
CFLAGS="${CFLAGS} -pg"
|
||||
LDFLAGS="${LDFLAGS} -pg")
|
||||
|
||||
# --enable-gpg doesn't mean GPG actually gets used; it just gets compiled
|
||||
# in. It can be potentially used to both receive and send information;
|
||||
# see src/gnome/gnc-gpg.c and PRIVACY for more information.
|
||||
|
||||
AC_ARG_ENABLE( gpg,
|
||||
[ --enable-gpg use GNU Privacy Guard for communications ],
|
||||
AC_DEFINE(USE_GPG,1),)
|
||||
|
||||
### --------------------------------------------------------------------------
|
||||
### SQL
|
||||
|
@ -27,6 +27,9 @@ src/gnome/glade-gnc-dialogs.c
|
||||
src/gnome/gnc-commodity-edit.c
|
||||
src/gnome/gnc-datedelta.c
|
||||
src/gnome/gnc-dateedit.c
|
||||
src/gnome/gnc-html.c
|
||||
src/gnome/gnc-http.c
|
||||
src/gnome/gnc-network.c
|
||||
src/gnome/new-user-interface.c
|
||||
src/gnome/print-session.c
|
||||
src/gnome/reconcile-list.c
|
||||
|
@ -34,11 +34,11 @@ libgncgnome_a_SOURCES = \
|
||||
gnc-datedelta.c \
|
||||
gnc-dateedit.c \
|
||||
gnc-gpg.c \
|
||||
gnc-html-actions.c \
|
||||
gnc-html-history.c \
|
||||
gnc-html-guppi.c \
|
||||
gnc-html.c \
|
||||
gnc-http.c \
|
||||
gnc-network.c \
|
||||
gnc-splash.c \
|
||||
gtkselect.c \
|
||||
mainwindow-account-tree.c \
|
||||
@ -92,11 +92,11 @@ noinst_HEADERS = \
|
||||
gnc-dateedit.h \
|
||||
gnc-dir.h \
|
||||
gnc-gpg.h \
|
||||
gnc-html-actions.h \
|
||||
gnc-html-history.h \
|
||||
gnc-html-guppi.h \
|
||||
gnc-html.h \
|
||||
gnc-http.h \
|
||||
gnc-network.h \
|
||||
gnc-splash.h \
|
||||
gtkselect.h \
|
||||
mainwindow-account-tree.h \
|
||||
|
@ -23,8 +23,6 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if USE_GPG
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <gnome.h>
|
||||
@ -37,254 +35,66 @@
|
||||
#include "global-options.h"
|
||||
#include "gnc-ui.h"
|
||||
#include "gnc-html.h"
|
||||
#include "gnc-network.h"
|
||||
#include "gnc-gpg.h"
|
||||
|
||||
/* handlers for embedded <object> tags */
|
||||
static int gnc_crypted_html_handler(gnc_html * html, GtkHTMLEmbedded * eb,
|
||||
gpointer d);
|
||||
static int gnc_make_keypair_handler(gnc_html * html, GtkHTMLEmbedded * eb,
|
||||
gpointer d);
|
||||
|
||||
/* handlers for gnc-action: <form> submit actions */
|
||||
static int gnc_submit_pubkey_handler(gnc_html * html,
|
||||
const char * method, const char * action,
|
||||
const char * act_args,
|
||||
GHashTable * form_data);
|
||||
|
||||
/********************************************************************
|
||||
* gnc_gpg_init : called at startup time. adds handlers for GPG
|
||||
* related network transactions
|
||||
* gnc_gpg_transform(_async) : call GPG with specified input and args
|
||||
* the _async variety returns immediately and calls a callback when
|
||||
* complete.
|
||||
********************************************************************/
|
||||
|
||||
void
|
||||
gnc_gpg_init(void) {
|
||||
gnc_html_register_object_handler("gnc-crypted-html",
|
||||
gnc_crypted_html_handler);
|
||||
gnc_html_register_object_handler("gnc-make-keypair",
|
||||
gnc_make_keypair_handler);
|
||||
|
||||
gnc_html_register_action_handler("submit-pubkey",
|
||||
gnc_submit_pubkey_handler);
|
||||
}
|
||||
|
||||
|
||||
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_get_passphrase : util to get a passphrase.
|
||||
********************************************************************/
|
||||
struct gpg_transform_data {
|
||||
GString * str;
|
||||
gint tag;
|
||||
GncGPGCb cb;
|
||||
gpointer data;
|
||||
};
|
||||
|
||||
static void
|
||||
get_pp_string_cb(char * string, gpointer data) {
|
||||
int l, i;
|
||||
gnc_gpg_transform_helper(gpointer data, gint fd, GdkInputCondition cond) {
|
||||
struct gpg_transform_data * td = data;
|
||||
int bytes_read;
|
||||
char buf[1025];
|
||||
char * cstr;
|
||||
|
||||
if(!data) return;
|
||||
if(!string) {
|
||||
*((char **)data) = NULL;
|
||||
}
|
||||
else {
|
||||
*((char **)data) = g_strdup(string);
|
||||
}
|
||||
}
|
||||
buf[1024] = 0;
|
||||
|
||||
static char *
|
||||
gnc_get_passphrase(const char * prompt) {
|
||||
char * pp = NULL;
|
||||
gint retval;
|
||||
GtkWidget * dlg =
|
||||
gnome_request_dialog(TRUE, prompt, "", 1024,
|
||||
get_pp_string_cb, (gpointer)&pp, NULL);
|
||||
retval = gnome_dialog_run(GNOME_DIALOG(dlg));
|
||||
if(retval == 0) {
|
||||
return pp;
|
||||
while((bytes_read = read(fd, buf, 1024)) == 1024) {
|
||||
g_string_append(td->str, buf);
|
||||
}
|
||||
else {
|
||||
printf("get_passphrase canceled.\n");
|
||||
return NULL;
|
||||
if(bytes_read > 0) {
|
||||
buf[bytes_read] = 0;
|
||||
g_string_append(td->str, buf);
|
||||
}
|
||||
else if(bytes_read == 0) {
|
||||
/* we're done. call the callback */
|
||||
gdk_input_remove(td->tag);
|
||||
cstr = td->str->str;
|
||||
g_string_free(td->str, FALSE);
|
||||
(td->cb)(cstr, td->data);
|
||||
g_free(td);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gnc_free_passphrase(char * pp) {
|
||||
int l, i;
|
||||
if(!pp) return;
|
||||
l = strlen(pp);
|
||||
for(i=0;i<l;i++) {
|
||||
pp[i]=0;
|
||||
}
|
||||
g_free(pp);
|
||||
}
|
||||
gnc_gpg_transform_async(const gchar * input, gint input_size,
|
||||
const char * passphrase, char ** gpg_argv,
|
||||
GncGPGCb cb, gpointer cb_data) {
|
||||
int pid;
|
||||
int to_child[2];
|
||||
int from_child[2];
|
||||
int bytes;
|
||||
int total_bytes;
|
||||
struct gpg_transform_data * td;
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* gnc_crypted_html_handler : receives ascii-armored GPG cryptext,
|
||||
* decrypts it, and displays the result as HTML.
|
||||
********************************************************************/
|
||||
|
||||
static int
|
||||
gnc_crypted_html_handler(gnc_html * html, GtkHTMLEmbedded * eb,
|
||||
gpointer data) {
|
||||
int retval = TRUE;
|
||||
char * cryptext = unescape_newlines(eb->data);
|
||||
char * passphrase = gnc_get_passphrase("Enter passphrase:");
|
||||
char * cleartext;
|
||||
|
||||
if(passphrase) {
|
||||
cleartext = gnc_gpg_decrypt(cryptext, strlen(cryptext), passphrase);
|
||||
if(cleartext && cleartext[0]) {
|
||||
gnc_html_show_data(html, cleartext, strlen(cleartext));
|
||||
}
|
||||
else {
|
||||
retval = FALSE;
|
||||
}
|
||||
g_free(cleartext);
|
||||
g_free(cryptext);
|
||||
gnc_free_passphrase(passphrase);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* gnc_make_keypair_handler : queries for a passphrase and
|
||||
* generates a keypair in the local keyring
|
||||
********************************************************************/
|
||||
|
||||
static int
|
||||
gnc_make_keypair_handler(gnc_html * html, GtkHTMLEmbedded * eb,
|
||||
gpointer data) {
|
||||
char * first_pp = NULL;
|
||||
char * verify_pp = NULL;
|
||||
char * username = g_hash_table_lookup(eb->params, "username");
|
||||
char * userid = g_hash_table_lookup(eb->params, "userid");
|
||||
char * email = g_hash_table_lookup(eb->params, "email");
|
||||
char * next_action = g_hash_table_lookup(eb->params, "next-action");
|
||||
char * cancel_action = g_hash_table_lookup(eb->params, "cancel-action");
|
||||
int retval = TRUE;
|
||||
URLType type;
|
||||
char * location = NULL;
|
||||
char * label = NULL;
|
||||
|
||||
first_pp = gnc_get_passphrase("Enter passphrase:");
|
||||
if(first_pp) {
|
||||
verify_pp = gnc_get_passphrase("Verify passphrase:");
|
||||
}
|
||||
else {
|
||||
type = gnc_html_parse_url(html, cancel_action, &location, &label);
|
||||
gnc_html_show_url(html, type, location, label, 0);
|
||||
g_free(location);
|
||||
g_free(label);
|
||||
}
|
||||
|
||||
if(verify_pp) {
|
||||
if(!strcmp(first_pp, verify_pp)) {
|
||||
printf("Got passphrase '%s' (shhh! don't tell). Generating keypair.\n",
|
||||
first_pp);
|
||||
gnc_gpg_make_keypair(username, userid, email, first_pp);
|
||||
printf("...done\n");
|
||||
gnc_free_passphrase(first_pp);
|
||||
gnc_free_passphrase(verify_pp);
|
||||
type = gnc_html_parse_url(html, next_action, &location, &label);
|
||||
gnc_html_show_url(html, type, location, label, 0);
|
||||
g_free(location);
|
||||
g_free(label);
|
||||
}
|
||||
else {
|
||||
gnc_free_passphrase(first_pp);
|
||||
gnc_free_passphrase(verify_pp);
|
||||
gnc_error_dialog(_("Passphrases did not match."));
|
||||
gnc_make_keypair_handler(html, eb, data);
|
||||
}
|
||||
}
|
||||
else {
|
||||
gnc_free_passphrase(first_pp);
|
||||
type = gnc_html_parse_url(html, cancel_action, &location, &label);
|
||||
gnc_html_show_url(html, type, location, label, 0);
|
||||
g_free(location);
|
||||
g_free(label);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* gnc_submit_pubkey_handler : send the public key as a multipart
|
||||
* POST submit
|
||||
********************************************************************/
|
||||
|
||||
static int
|
||||
gnc_submit_pubkey_handler(gnc_html * html, const char * method,
|
||||
const char * action, const char * args,
|
||||
GHashTable * form_data) {
|
||||
char * keyid = g_hash_table_lookup(form_data, "gnc_keyid");
|
||||
char * submit = g_hash_table_lookup(form_data, "submit");
|
||||
char * keytext = NULL;
|
||||
char * gnc_net_server =
|
||||
gnc_lookup_string_option("Network", "GnuCash Network server",
|
||||
"www.gnumatic.com");
|
||||
char * new_action = g_strconcat("http://", gnc_net_server, "/", args, NULL);
|
||||
|
||||
if(!strcmp(submit, "OK")) {
|
||||
/* get the public key */
|
||||
if(keyid) {
|
||||
keytext = gnc_gpg_export(keyid);
|
||||
}
|
||||
|
||||
/* stick it in the form data */
|
||||
g_hash_table_insert(form_data, g_strdup("gnc_user_pubkey"), keytext);
|
||||
|
||||
/* submit as a multipart form */
|
||||
gnc_html_multipart_post_submit(html, new_action, form_data);
|
||||
}
|
||||
else {
|
||||
/* don't export the pubkey, just submit as is. */
|
||||
printf("canceled\n");
|
||||
gnc_html_generic_post_submit(html, new_action, form_data);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static char *
|
||||
gnc_gpg_transform(const gchar * input, gint input_size,
|
||||
const char * passphrase, char ** gpg_argv) {
|
||||
int pid;
|
||||
int to_child[2];
|
||||
int from_child[2];
|
||||
int bytes;
|
||||
int block_bytes;
|
||||
int total_bytes;
|
||||
GList * data = NULL;
|
||||
GList * blockptr;
|
||||
char * current_blk = NULL;
|
||||
char * retval;
|
||||
char * insert_pos;
|
||||
|
||||
/* create a pipe for talking to the child gpg process */
|
||||
if((pipe(to_child) != 0) || (pipe(from_child) != 0)) {
|
||||
return NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* create the process. */
|
||||
if((pid = fork()) != 0) {
|
||||
close(to_child[0]);
|
||||
close(from_child[1]);
|
||||
@ -314,36 +124,15 @@ gnc_gpg_transform(const gchar * input, gint input_size,
|
||||
}
|
||||
close(to_child[1]);
|
||||
|
||||
/* read transformed data back */
|
||||
current_blk = g_new0(char, 1024);
|
||||
block_bytes = 0;
|
||||
total_bytes = 0;
|
||||
|
||||
while((bytes = read(from_child[0], current_blk, 1024-block_bytes)) > 0) {
|
||||
block_bytes += bytes;
|
||||
total_bytes += bytes;
|
||||
if(block_bytes == 1024) {
|
||||
data = g_list_append(data, current_blk);
|
||||
current_blk = g_new0(char, 1024);
|
||||
block_bytes = 0;
|
||||
}
|
||||
}
|
||||
td = g_new0(struct gpg_transform_data, 1);
|
||||
td->str = g_string_new("");
|
||||
td->cb = cb;
|
||||
td->data = cb_data;
|
||||
|
||||
/* collapse the output text into a single array */
|
||||
retval = g_new0(char, total_bytes);
|
||||
insert_pos = retval;
|
||||
for(blockptr = data; blockptr; blockptr = blockptr->next) {
|
||||
memcpy(insert_pos, blockptr->data, 1024);
|
||||
g_free(blockptr->data);
|
||||
blockptr->data = NULL;
|
||||
insert_pos += 1024;
|
||||
}
|
||||
memcpy(insert_pos, current_blk, block_bytes);
|
||||
g_free(current_blk);
|
||||
g_list_free(data);
|
||||
|
||||
return retval;
|
||||
}
|
||||
/* read transformed data back in the input handler */
|
||||
td->tag = gdk_input_add(from_child[0], GDK_INPUT_READ,
|
||||
gnc_gpg_transform_helper, td);
|
||||
}
|
||||
else {
|
||||
close(to_child[1]);
|
||||
close(from_child[0]);
|
||||
@ -363,10 +152,30 @@ gnc_gpg_transform(const gchar * input, gint input_size,
|
||||
if(execvp("gpg", gpg_argv)) {
|
||||
exit(-1);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gnc_gpg_transform_sync_helper(char * output, gpointer data) {
|
||||
const char ** status = data;
|
||||
status[1] = output;
|
||||
status[0] = (char *)1;
|
||||
|
||||
}
|
||||
|
||||
static char *
|
||||
gnc_gpg_transform(const gchar * input, gint input_size,
|
||||
const char * passphrase, char ** gpg_argv) {
|
||||
char * out[2] = { NULL, NULL };
|
||||
gnc_gpg_transform_async(input, input_size, passphrase, gpg_argv,
|
||||
gnc_gpg_transform_sync_helper, (gpointer)out);
|
||||
while(!out[0]) {
|
||||
gtk_main_iteration();
|
||||
}
|
||||
return out[1];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* gnc_gpg_encrypt
|
||||
@ -400,6 +209,34 @@ gnc_gpg_encrypt(const gchar * cleartext, int cleartext_size,
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
gnc_gpg_encrypt_async(const gchar * cleartext, int cleartext_size,
|
||||
const gchar * recipient, const gchar * passphrase,
|
||||
GncGPGCb cb, gpointer data) {
|
||||
char * retval = NULL;
|
||||
char * argv[] =
|
||||
{
|
||||
"gpg",
|
||||
"-q",
|
||||
"--batch",
|
||||
"-sea",
|
||||
"--keyring",
|
||||
"~/.gnucash/gnucash.pub",
|
||||
"--secret-keyring",
|
||||
"~/.gnucash/gnucash.sec",
|
||||
"-r",
|
||||
NULL,
|
||||
"--passphrase-fd",
|
||||
"0",
|
||||
NULL
|
||||
};
|
||||
|
||||
argv[7] = (char *)recipient;
|
||||
|
||||
gnc_gpg_transform_async(cleartext, cleartext_size, passphrase, argv,
|
||||
cb, data);
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* gnc_gpg_decrypt
|
||||
@ -410,7 +247,7 @@ char *
|
||||
gnc_gpg_decrypt(const gchar * cryptext, int cryptext_size,
|
||||
const gchar * passphrase) {
|
||||
char * retval = NULL;
|
||||
|
||||
|
||||
char * argv[] =
|
||||
{ "gpg",
|
||||
"-q",
|
||||
@ -424,12 +261,36 @@ gnc_gpg_decrypt(const gchar * cryptext, int cryptext_size,
|
||||
"0",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
retval = gnc_gpg_transform(cryptext, cryptext_size, passphrase, argv);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
gnc_gpg_decrypt_async(const gchar * cryptext, int cryptext_size,
|
||||
const gchar * passphrase,
|
||||
void (* cb)(char * clrtxt, gpointer d),
|
||||
gpointer data) {
|
||||
char * retval = NULL;
|
||||
|
||||
char * argv[] =
|
||||
{ "gpg",
|
||||
"-q",
|
||||
"--batch",
|
||||
"-da",
|
||||
"--keyring",
|
||||
"~/.gnucash/gnucash.pub",
|
||||
"--secret-keyring",
|
||||
"~/.gnucash/gnucash.sec",
|
||||
"--passphrase-fd",
|
||||
"0",
|
||||
NULL
|
||||
};
|
||||
|
||||
gnc_gpg_transform_async(cryptext, cryptext_size, passphrase, argv,
|
||||
cb, data);
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* gnc_gpg_export
|
||||
@ -444,21 +305,42 @@ gnc_gpg_export(const gchar * keyname) {
|
||||
"-q",
|
||||
"--export",
|
||||
"-a",
|
||||
"--keyring",
|
||||
"~/.gnucash/gnucash.pub",
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
argv[4] = keyname;
|
||||
argv[6] = g_strdup_printf("(%s)", keyname);
|
||||
retval = gnc_gpg_transform(NULL, 0, NULL, argv);
|
||||
g_free(argv[6]);
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
gnc_gpg_export_async(const gchar * keyname, GncGPGCb cb, gpointer data) {
|
||||
char * retval;
|
||||
char * argv[] =
|
||||
{ "gpg",
|
||||
"-q",
|
||||
"--export",
|
||||
"-a",
|
||||
"--keyring",
|
||||
"~/.gnucash/gnucash.pub",
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
argv[6] = g_strdup_printf("(%s)", keyname);
|
||||
gnc_gpg_transform_async(NULL, 0, NULL, argv, cb, data);
|
||||
g_free(argv[6]);
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* gnc_gpg_make_keypair
|
||||
* make a keypair for gnucash use
|
||||
********************************************************************/
|
||||
|
||||
void
|
||||
char *
|
||||
gnc_gpg_make_keypair(const gchar * username,
|
||||
const gchar * idstring,
|
||||
const gchar * email,
|
||||
@ -488,6 +370,38 @@ gnc_gpg_make_keypair(const gchar * username,
|
||||
|
||||
char * retval = gnc_gpg_transform(stdin, strlen(stdin), NULL, argv);
|
||||
g_free(stdin);
|
||||
return retval;
|
||||
}
|
||||
|
||||
#endif
|
||||
void
|
||||
gnc_gpg_make_keypair_async(const gchar * username,
|
||||
const gchar * idstring,
|
||||
const gchar * email,
|
||||
const gchar * passphrase,
|
||||
GncGPGCb cb, gpointer data) {
|
||||
char * stdin =
|
||||
g_strdup_printf("Key-Type: DSA\n"
|
||||
"Key-Length: 1024\n"
|
||||
"Subkey-Type: ELG-E\n"
|
||||
"Subkey-Length: 1024\n"
|
||||
"Name-Real: %s\n"
|
||||
"Name-Comment: %s\n"
|
||||
"Name-Email: %s\n"
|
||||
"Passphrase: %s\n"
|
||||
"%%commit\n",
|
||||
username, idstring, email, passphrase);
|
||||
char * argv [] =
|
||||
{ "gpg",
|
||||
"--batch",
|
||||
"-q",
|
||||
"--gen-key",
|
||||
"--keyring",
|
||||
"~/.gnucash/gnucash.pub",
|
||||
"--secret-keyring",
|
||||
"~/.gnucash/gnucash.sec",
|
||||
NULL
|
||||
};
|
||||
|
||||
gnc_gpg_transform_async(stdin, strlen(stdin), NULL, argv, cb, data);
|
||||
g_free(stdin);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/********************************************************************
|
||||
* gnc-gpg.h -- encrypt/decrypt data using GPG and the gnucash *
|
||||
* keyrings *
|
||||
* Copyright (C) 2000 Bill Gribble <grib@billgribble.com> *
|
||||
* Copyright (C) 2000-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 *
|
||||
@ -24,15 +24,31 @@
|
||||
#ifndef __GNC_GPG_H__
|
||||
#define __GNC_GPG_H__
|
||||
|
||||
#include "config.h"
|
||||
#include <glib.h>
|
||||
|
||||
typedef void (* GncGPGCb)(char * output, gpointer data);
|
||||
|
||||
void gnc_gpg_init(void);
|
||||
char * gnc_gpg_export(const gchar * keyname);
|
||||
void gnc_gpg_export_async(const gchar * keyname, GncGPGCb cb,
|
||||
gpointer data);
|
||||
|
||||
char * gnc_gpg_encrypt(const gchar * cleartext, int cleartext_size,
|
||||
const gchar * recipient, const gchar * passphrase);
|
||||
char * gnc_gpg_decrypt(const gchar * cleartext, int cleartext_size,
|
||||
void gnc_gpg_encrypt_async(const gchar * cleartext, int cleartext_size,
|
||||
const gchar * recipient, const gchar * pp,
|
||||
GncGPGCb cb, gpointer data);
|
||||
|
||||
char * gnc_gpg_decrypt(const gchar * crypttext, int crypttext_size,
|
||||
const gchar * passphrase);
|
||||
void gnc_gpg_make_keypair(const gchar * name, const gchar * id,
|
||||
const gchar * email, const gchar * passphrase);
|
||||
void gnc_gpg_decrypt_async(const gchar * crypttext, int crypttext_size,
|
||||
const gchar * passphrase,
|
||||
GncGPGCb cb, gpointer data);
|
||||
|
||||
char * gnc_gpg_make_keypair(const gchar * name, const gchar * id,
|
||||
const gchar * email, const gchar * passphrase);
|
||||
void gnc_gpg_make_keypair_async(const gchar * name, const gchar * id,
|
||||
const gchar * email, const gchar * pp,
|
||||
GncGPGCb cb, gpointer data);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -1,143 +0,0 @@
|
||||
/********************************************************************
|
||||
* 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
|
||||
* (the "GnuCash Network") 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
|
||||
* only web server that will have such forms will be the GnuCash
|
||||
* Network server. Even if other hosts try to fool gnucash with
|
||||
* GnuCash Network submit actions, we will only ever submit to the
|
||||
* user's specified GnuCash Network server.
|
||||
*
|
||||
* 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 ("Enable GnuCash Network").
|
||||
*
|
||||
* 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. A server-side confirmation is probably enough, but
|
||||
* client-side confirm is better.
|
||||
*
|
||||
* 2. Do not 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. Always use the "GnuCash Network
|
||||
* server" from the global preferences option.
|
||||
********************************************************************/
|
||||
|
||||
#include "config.h"
|
||||
#include <string.h>
|
||||
#include <glib.h>
|
||||
#include <guile/gh.h>
|
||||
|
||||
#include "global-options.h"
|
||||
#include "gnc-html-actions.h"
|
||||
#include "gnc-html.h"
|
||||
|
||||
static int
|
||||
gnc_info_form_submit_handler(gnc_html * html, const char * method,
|
||||
const char * action, const char * args,
|
||||
GHashTable * form_data);
|
||||
|
||||
/********************************************************************
|
||||
* 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",
|
||||
gnc_info_form_submit_handler);
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* gnc_info_form_submit_handler() : submit the form arguments from
|
||||
* 'encoding', appending additional arguments describing the gnucash
|
||||
* client: gnucash version string and some features.
|
||||
********************************************************************/
|
||||
|
||||
static int
|
||||
gnc_info_form_submit_handler(gnc_html * html, const char * method,
|
||||
const char * action, const char * args,
|
||||
GHashTable * form_data) {
|
||||
char * version_string = NULL;
|
||||
char * new_action = NULL;
|
||||
char * gnc_net_server =
|
||||
gnc_lookup_string_option("Network", "GnuCash Network server",
|
||||
"www.gnumatic.com");
|
||||
char * feature_string = NULL;
|
||||
|
||||
if(!method || !action
|
||||
|| strcmp(action, "gnc-info/form")) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
version_string = gh_scm2newstr(gh_eval_str("gnc:version"), NULL);
|
||||
|
||||
feature_string =
|
||||
g_strjoin(",",
|
||||
#if USE_GUPPI
|
||||
"guppi",
|
||||
#endif
|
||||
#if USE_GPG
|
||||
"gpg",
|
||||
#endif
|
||||
#if HAVE_OPENSSL
|
||||
"openssl",
|
||||
#endif
|
||||
NULL);
|
||||
g_hash_table_insert(form_data, g_strdup("gnc_browser"), g_strdup("1"));
|
||||
g_hash_table_insert(form_data, g_strdup("gnc_version"),
|
||||
g_strdup(version_string));
|
||||
g_hash_table_insert(form_data, g_strdup("gnc_features"),
|
||||
feature_string);
|
||||
free(version_string);
|
||||
|
||||
new_action = g_strconcat("http://", gnc_net_server, "/", args, NULL);
|
||||
|
||||
if(!strcasecmp(method, "get")) {
|
||||
gnc_html_generic_get_submit(html, new_action, form_data);
|
||||
}
|
||||
else {
|
||||
gnc_html_generic_post_submit(html, new_action, form_data);
|
||||
}
|
||||
|
||||
g_free(gnc_net_server);
|
||||
g_free(new_action);
|
||||
return TRUE;
|
||||
}
|
@ -55,12 +55,14 @@
|
||||
#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-network.h"
|
||||
#include "query-user.h"
|
||||
#include "window-help.h"
|
||||
#include "window-report.h"
|
||||
#include "messages.h"
|
||||
|
||||
|
||||
struct _gnc_html {
|
||||
GtkWidget * container; /* parent of the gtkhtml widget */
|
||||
@ -108,6 +110,30 @@ static char error_report[] =
|
||||
"<html><body><h3>Report error</h3><p>An error occurred while running the report.</body></html>";
|
||||
|
||||
|
||||
static char *
|
||||
extract_machine_name(const gchar * path) {
|
||||
char machine_rexp[] = "^(//[^/]*)/*(.*)?$";
|
||||
regex_t compiled_m;
|
||||
regmatch_t match[4];
|
||||
char * machine=NULL;
|
||||
|
||||
if(!path) return NULL;
|
||||
|
||||
regcomp(&compiled_m, machine_rexp, REG_EXTENDED);
|
||||
|
||||
/* step 1: split the machine name away from the path
|
||||
* components */
|
||||
if(!regexec(&compiled_m, path, 4, match, 0)) {
|
||||
/* $1 is the machine name */
|
||||
if(match[1].rm_so != -1) {
|
||||
machine = g_strndup(path+match[1].rm_so,
|
||||
match[1].rm_eo - match[1].rm_so);
|
||||
}
|
||||
}
|
||||
return machine;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* gnc_html_parse_url
|
||||
* this takes a URL and determines the protocol type, location, and
|
||||
@ -197,21 +223,20 @@ gnc_html_parse_url(gnc_html * html, const gchar * url,
|
||||
switch(retval) {
|
||||
case URL_TYPE_FILE:
|
||||
if(!found_protocol && path && html->base_location) {
|
||||
*url_location = g_new0(char,
|
||||
strlen(path) + strlen(html->base_location) + 1);
|
||||
*url_location[0] = 0;
|
||||
|
||||
strcpy(*url_location, html->base_location);
|
||||
strcat(*url_location, "/");
|
||||
strcat(*url_location, path);
|
||||
|
||||
if(path[0] == '/') {
|
||||
*url_location = g_strdup(path);
|
||||
}
|
||||
else {
|
||||
*url_location = g_strconcat(html->base_location, path, NULL);
|
||||
}
|
||||
g_free(path);
|
||||
}
|
||||
else {
|
||||
*url_location = path;
|
||||
*url_location = g_strdup(path);
|
||||
g_free(path);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case URL_TYPE_JUMP:
|
||||
*url_location = NULL;
|
||||
g_free(path);
|
||||
@ -220,15 +245,19 @@ gnc_html_parse_url(gnc_html * html, const gchar * url,
|
||||
case URL_TYPE_OTHER:
|
||||
default:
|
||||
if(!found_protocol && path && html->base_location) {
|
||||
*url_location = g_new0(char,
|
||||
strlen(path) + strlen(html->base_location) + 1);
|
||||
*url_location[0] = 0;
|
||||
strcpy(*url_location, html->base_location);
|
||||
strcat(*url_location, path);
|
||||
if(path[0] == '/') {
|
||||
*url_location =
|
||||
g_strconcat(extract_machine_name(html->base_location),
|
||||
"/", path+1, NULL);
|
||||
}
|
||||
else {
|
||||
*url_location = g_strconcat(html->base_location, path, NULL);
|
||||
}
|
||||
g_free(path);
|
||||
}
|
||||
else {
|
||||
*url_location = path;
|
||||
*url_location = g_strdup(path);
|
||||
g_free(path);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -240,71 +269,83 @@ gnc_html_parse_url(gnc_html * html, const gchar * url,
|
||||
|
||||
static char *
|
||||
extract_base_name(URLType type, const gchar * path) {
|
||||
char http_rexp[] = "^(//[^/]*)(/.*)?$";
|
||||
char other_rexp[] = "^(.*)(/([^/]*))?$";
|
||||
regex_t compiled_h, compiled_o;
|
||||
char machine_rexp[] = "^(//[^/]*)/*(/.*)?$";
|
||||
char path_rexp[] = "^/*(.*)/+([^/]*)$";
|
||||
regex_t compiled_m, compiled_p;
|
||||
regmatch_t match[4];
|
||||
char * machine=NULL, * location = NULL, * base=NULL;
|
||||
|
||||
regcomp(&compiled_h, http_rexp, REG_EXTENDED);
|
||||
regcomp(&compiled_o, other_rexp, REG_EXTENDED);
|
||||
char * basename=NULL;
|
||||
|
||||
if(!path) return NULL;
|
||||
|
||||
regcomp(&compiled_m, machine_rexp, REG_EXTENDED);
|
||||
regcomp(&compiled_p, path_rexp, REG_EXTENDED);
|
||||
|
||||
switch(type) {
|
||||
case URL_TYPE_HTTP:
|
||||
case URL_TYPE_SECURE:
|
||||
case URL_TYPE_FTP:
|
||||
if(!regexec(&compiled_h, path, 4, match, 0)) {
|
||||
/* step 1: split the machine name away from the path
|
||||
* components */
|
||||
if(!regexec(&compiled_m, path, 4, match, 0)) {
|
||||
/* $1 is the machine name */
|
||||
if(match[1].rm_so != -1) {
|
||||
machine = g_new0(char, strlen(path) + 2);
|
||||
strncpy(machine, path+match[1].rm_so,
|
||||
match[1].rm_eo - match[1].rm_so);
|
||||
machine = g_strndup(path+match[1].rm_so,
|
||||
match[1].rm_eo - match[1].rm_so);
|
||||
}
|
||||
/* $2 is the path */
|
||||
if(match[2].rm_so != -1) {
|
||||
location = g_new0(char, match[2].rm_eo - match[2].rm_so + 1);
|
||||
strncpy(location, path+match[2].rm_so,
|
||||
match[2].rm_eo - match[2].rm_so);
|
||||
location = g_strndup(path+match[2].rm_so,
|
||||
match[2].rm_eo - match[2].rm_so);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
location = g_strdup(path);
|
||||
}
|
||||
|
||||
/* step 2: split up the path into prefix and file components */
|
||||
if(location) {
|
||||
if(!regexec(&compiled_o, location, 4, match, 0)) {
|
||||
if(match[2].rm_so != -1) {
|
||||
base = g_new0(char, match[1].rm_eo - match[1].rm_so + 1);
|
||||
strncpy(base, path+match[1].rm_so,
|
||||
match[1].rm_eo - match[1].rm_so);
|
||||
if(!regexec(&compiled_p, location, 4, match, 0)) {
|
||||
if(match[1].rm_so != -1) {
|
||||
base = g_strndup(location+match[1].rm_so,
|
||||
match[1].rm_eo - match[1].rm_so);
|
||||
}
|
||||
else {
|
||||
base = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
regfree(&compiled_h);
|
||||
regfree(&compiled_o);
|
||||
|
||||
g_free(location);
|
||||
|
||||
regfree(&compiled_m);
|
||||
regfree(&compiled_p);
|
||||
|
||||
if(machine) {
|
||||
strcat(machine, "/");
|
||||
if(base) {
|
||||
strcat(machine, base);
|
||||
if(base && (strlen(base) > 0)) {
|
||||
basename = g_strconcat(machine, "/", base, "/", NULL);
|
||||
}
|
||||
else {
|
||||
basename = g_strconcat(machine, "/", NULL);
|
||||
}
|
||||
g_free(base);
|
||||
return machine;
|
||||
}
|
||||
else {
|
||||
g_free(machine);
|
||||
return base;
|
||||
if(base && (strlen(base) > 0)) {
|
||||
basename = g_strdup(base);
|
||||
}
|
||||
else {
|
||||
basename = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
g_free(machine);
|
||||
g_free(base);
|
||||
g_free(location);
|
||||
return basename;
|
||||
}
|
||||
|
||||
static char * url_type_names[] = {
|
||||
"file:", "", "http:", "ftp:", "https:",
|
||||
"gnc-register:", "gnc-report:", "gnc-scm:",
|
||||
"gnc-help:", ""
|
||||
"gnc-help:", "gnc-xml:", "gnc-action:", ""
|
||||
};
|
||||
|
||||
|
||||
@ -353,20 +394,38 @@ gnc_html_http_request_cb(const gchar * uri, int completed_ok,
|
||||
URLType type;
|
||||
char * location = NULL;
|
||||
char * label = NULL;
|
||||
GList * handles;
|
||||
GList * handles = NULL;
|
||||
GList * current;
|
||||
|
||||
handles = g_hash_table_lookup(html->request_info, uri);
|
||||
|
||||
|
||||
g_hash_table_lookup_extended(html->request_info, uri,
|
||||
(gpointer *)&location,
|
||||
(gpointer *)&handles);
|
||||
|
||||
/* handles will be NULL for an HTTP POST transaction, where we are
|
||||
* displaying the reply data. */
|
||||
if(!handles) {
|
||||
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);
|
||||
if(completed_ok) {
|
||||
gtk_html_write(GTK_HTML(html->html), handle, body, body_len);
|
||||
}
|
||||
else {
|
||||
gtk_html_write(GTK_HTML(html->html), handle,
|
||||
error_start, strlen(error_start));
|
||||
gtk_html_write(GTK_HTML(html->html), handle,
|
||||
body, body_len);
|
||||
gtk_html_write(GTK_HTML(html->html), handle,
|
||||
error_end, strlen(error_end));
|
||||
gtk_html_end(GTK_HTML(html->html), handle, GTK_HTML_STREAM_OK);
|
||||
}
|
||||
}
|
||||
/* otherwise, it's a normal SUBMIT transaction */
|
||||
else {
|
||||
/* before writing to the handles, make sure any new traffic won't
|
||||
* see them while we're working */
|
||||
g_hash_table_remove(html->request_info, uri);
|
||||
g_free(location);
|
||||
location = NULL;
|
||||
|
||||
for(current = handles; current; current = current->next) {
|
||||
/* request completed OK... write the HTML to the handles that
|
||||
* asked for that URI. */
|
||||
@ -395,19 +454,9 @@ gnc_html_http_request_cb(const gchar * uri, int completed_ok,
|
||||
GTK_HTML_STREAM_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
g_list_free(handles);
|
||||
}
|
||||
|
||||
|
||||
gnc_unset_busy_cursor (html->html);
|
||||
}
|
||||
|
||||
@ -495,8 +544,10 @@ gnc_html_load_to_stream(gnc_html * html, GtkHTMLStream * handle,
|
||||
"You can enable it in the Network section of\n"
|
||||
"the Preferences dialog.");
|
||||
}
|
||||
fullurl = rebuild_url(type, location, label);
|
||||
gnc_html_start_request(html, fullurl, handle);
|
||||
else {
|
||||
fullurl = rebuild_url(type, location, label);
|
||||
gnc_html_start_request(html, fullurl, handle);
|
||||
}
|
||||
break;
|
||||
|
||||
case URL_TYPE_REPORT:
|
||||
@ -758,24 +809,35 @@ gnc_html_button_press_cb(GtkWidget * widg, GdkEventButton * event,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* gnc_html_pack/unpack_form_data
|
||||
* convert an encoded arg string to/from a name-value hash table
|
||||
********************************************************************/
|
||||
|
||||
static GHashTable *
|
||||
GHashTable *
|
||||
gnc_html_unpack_form_data(const char * encoding) {
|
||||
GHashTable * rv = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
gnc_html_merge_form_data(rv, encoding);
|
||||
return rv;
|
||||
}
|
||||
|
||||
char * next_pair = g_strdup(encoding);
|
||||
void
|
||||
gnc_html_merge_form_data(GHashTable * rv, const char * encoding) {
|
||||
char * next_pair = NULL;
|
||||
char * name = NULL;
|
||||
char * value = NULL;
|
||||
char * extr_name = NULL;
|
||||
char * extr_value = NULL;
|
||||
|
||||
if(!encoding) {
|
||||
return;
|
||||
}
|
||||
next_pair = g_strdup(encoding);
|
||||
|
||||
while(next_pair) {
|
||||
name = next_pair;
|
||||
if((value = strchr(name, '='))) {
|
||||
if((value = strchr(name, '=')) != NULL) {
|
||||
extr_name = g_strndup(name, value-name);
|
||||
next_pair = strchr(value, '&');
|
||||
if(next_pair) {
|
||||
@ -796,8 +858,6 @@ gnc_html_unpack_form_data(const char * encoding) {
|
||||
next_pair = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -807,7 +867,7 @@ free_form_data_helper(gpointer k, gpointer v, gpointer user) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
gnc_html_free_form_data(GHashTable * d) {
|
||||
g_hash_table_foreach_remove(d, free_form_data_helper, NULL);
|
||||
g_hash_table_destroy(d);
|
||||
@ -831,7 +891,7 @@ pack_form_data_helper(gpointer key, gpointer val,
|
||||
g_free(old_str);
|
||||
}
|
||||
|
||||
static char *
|
||||
char *
|
||||
gnc_html_pack_form_data(GHashTable * form_data) {
|
||||
char * encoded = NULL;
|
||||
g_hash_table_foreach(form_data, pack_form_data_helper, &encoded);
|
||||
@ -865,9 +925,10 @@ gnc_html_submit_cb(GtkHTML * html, const gchar * method,
|
||||
if(gnc_html_action_handlers) {
|
||||
action_parts = g_strsplit(location, "?", 2);
|
||||
if(action_parts && action_parts[0]) {
|
||||
gnc_html_merge_form_data(form_data, action_parts[1]);
|
||||
cb = g_hash_table_lookup(gnc_html_action_handlers, action_parts[0]);
|
||||
if(cb) {
|
||||
cb(gnchtml, method, action_parts[0], action_parts[1], form_data);
|
||||
cb(gnchtml, method, action_parts[0], form_data);
|
||||
}
|
||||
else {
|
||||
PWARN ("no handler for gnc-network action '%s'\n", action);
|
||||
@ -879,10 +940,10 @@ gnc_html_submit_cb(GtkHTML * html, const gchar * method,
|
||||
}
|
||||
}
|
||||
else {
|
||||
gnc_error_dialog("GnuCash Network is disabled and this page "
|
||||
"requires it.\n"
|
||||
"You can enable it in the Network section\n"
|
||||
"of the Preferences dialog.");
|
||||
gnc_error_dialog(_("GnuCash Network is disabled and the link "
|
||||
"you have clicked requires it.\n"
|
||||
"You can enable it in the Network section\n"
|
||||
"of the Preferences dialog."));
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -1091,6 +1152,10 @@ gnc_html_show_url(gnc_html * html, URLType type,
|
||||
newwin = 1;
|
||||
}
|
||||
|
||||
if(!newwin) {
|
||||
gnc_html_cancel(html);
|
||||
}
|
||||
|
||||
switch(type) {
|
||||
case URL_TYPE_REGISTER:
|
||||
gnc_html_open_register(html, location);
|
||||
@ -1114,16 +1179,16 @@ gnc_html_show_url(gnc_html * html, URLType type,
|
||||
|
||||
case URL_TYPE_SECURE:
|
||||
if(!https_allowed()) {
|
||||
gnc_error_dialog("Secure HTTP access is disabled.\n"
|
||||
"You can enable it in the Network section of\n"
|
||||
"the Preferences dialog.");
|
||||
gnc_error_dialog(_("Secure HTTP access is disabled.\n"
|
||||
"You can enable it in the Network section of\n"
|
||||
"the Preferences dialog."));
|
||||
break;
|
||||
}
|
||||
case URL_TYPE_HTTP:
|
||||
if(!http_allowed()) {
|
||||
gnc_error_dialog("Network HTTP access is disabled.\n"
|
||||
"You can enable it in the Network section of\n"
|
||||
"the Preferences dialog.");
|
||||
gnc_error_dialog(_("Network HTTP access is disabled.\n"
|
||||
"You can enable it in the Network section of\n"
|
||||
"the Preferences dialog."));
|
||||
break;
|
||||
}
|
||||
case URL_TYPE_FILE:
|
||||
@ -1131,7 +1196,7 @@ gnc_html_show_url(gnc_html * html, URLType type,
|
||||
|
||||
if(html->base_location) g_free(html->base_location);
|
||||
html->base_location = extract_base_name(type, location);
|
||||
|
||||
|
||||
/* FIXME : handle newwin = 1 */
|
||||
gnc_html_history_append(html->history,
|
||||
gnc_html_history_node_new(type, location, label));
|
||||
@ -1139,6 +1204,15 @@ gnc_html_show_url(gnc_html * html, URLType type,
|
||||
gnc_html_load_to_stream(html, handle, type, location, label);
|
||||
break;
|
||||
|
||||
case URL_TYPE_ACTION:
|
||||
gnc_html_history_append(html->history,
|
||||
gnc_html_history_node_new(type,
|
||||
location, label));
|
||||
gnc_html_submit_cb(GTK_HTML(html->html), "get",
|
||||
rebuild_url(type, location, label), NULL,
|
||||
(gpointer)html);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1233,9 +1307,19 @@ gnc_html_new(void) {
|
||||
* cancel any outstanding HTML fetch requests.
|
||||
********************************************************************/
|
||||
|
||||
static gboolean
|
||||
html_cancel_helper(gpointer key, gpointer value, gpointer user_data) {
|
||||
g_free(key);
|
||||
g_list_free((GList *)value);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
gnc_html_cancel(gnc_html * html) {
|
||||
/* remove our own references to requests */
|
||||
gnc_http_cancel_requests(html->http);
|
||||
|
||||
g_hash_table_foreach_remove(html->request_info, html_cancel_helper, NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -1423,6 +1507,8 @@ gnc_html_encode_string(const char * str) {
|
||||
gchar buffer[5], *ptr;
|
||||
guchar c;
|
||||
|
||||
if(!str) return NULL;
|
||||
|
||||
while(pos < strlen(str)) {
|
||||
c = (unsigned char) str[pos];
|
||||
|
||||
@ -1461,6 +1547,9 @@ gnc_html_decode_string(const char * str) {
|
||||
guchar c;
|
||||
guint hexval;
|
||||
ptr = str;
|
||||
|
||||
if(!str) return NULL;
|
||||
|
||||
while(*ptr) {
|
||||
c = (unsigned char) *ptr;
|
||||
if ((( c >= 'A') && ( c <= 'Z')) ||
|
||||
@ -1490,6 +1579,52 @@ gnc_html_decode_string(const char * str) {
|
||||
return (char *)ptr;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* escape/unescape_newlines : very simple string encoding for GPG
|
||||
* ASCII-armored text.
|
||||
********************************************************************/
|
||||
|
||||
char *
|
||||
gnc_html_unescape_newlines(const gchar * in) {
|
||||
const char * ip = in;
|
||||
char * cstr = NULL;
|
||||
GString * rv = g_string_new("");
|
||||
|
||||
for(ip=in; *ip; ip++) {
|
||||
if((*ip == '\\') && (*(ip+1)=='n')) {
|
||||
g_string_append(rv, "\n");
|
||||
ip++;
|
||||
}
|
||||
else {
|
||||
g_string_append_c(rv, *ip);
|
||||
}
|
||||
}
|
||||
|
||||
g_string_append_c(rv, 0);
|
||||
cstr = rv->str;
|
||||
g_string_free(rv, FALSE);
|
||||
return cstr;
|
||||
}
|
||||
|
||||
char *
|
||||
gnc_html_escape_newlines(const gchar * in) {
|
||||
const char * ip = in;
|
||||
GString * escaped = g_string_new("");
|
||||
|
||||
for(ip=in; *ip; ip++) {
|
||||
if(*ip == '\012') {
|
||||
g_string_append(escaped, "\\n");
|
||||
}
|
||||
else {
|
||||
g_string_append_c(escaped, *ip);
|
||||
}
|
||||
}
|
||||
g_string_append_c(escaped, 0);
|
||||
ip = escaped->str;
|
||||
g_string_free(escaped, FALSE);
|
||||
return ip;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/********************************************************************
|
||||
@ -1524,9 +1659,10 @@ void
|
||||
gnc_html_generic_post_submit(gnc_html * html, const char * action,
|
||||
GHashTable * form_data) {
|
||||
char * encoded = gnc_html_pack_form_data(form_data);
|
||||
char * copy = strdup(encoded);
|
||||
gnc_http_start_post(html->http, action,
|
||||
"application/x-www-form-urlencoded",
|
||||
encoded, strlen(encoded),
|
||||
copy, strlen(copy),
|
||||
gnc_html_http_request_cb, html);
|
||||
g_free(encoded);
|
||||
}
|
||||
@ -1574,7 +1710,5 @@ gnc_html_multipart_post_submit(gnc_html * html, const char * action,
|
||||
htmlstr, strlen(htmlstr),
|
||||
gnc_html_http_request_cb, html);
|
||||
|
||||
printf("==== multipart submit ====\n");
|
||||
printf("%s\n==== end ====\n", htmlstr);
|
||||
g_free(htmlstr);
|
||||
}
|
||||
|
@ -54,8 +54,8 @@ typedef int (* GncHTMLButtonCB)(gnc_html * html, GdkEventButton * event,
|
||||
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,
|
||||
GHashTable * form_data);
|
||||
const char * action, GHashTable * form_data);
|
||||
|
||||
gnc_html * gnc_html_new(void);
|
||||
void gnc_html_destroy(gnc_html * html);
|
||||
void gnc_html_show_url(gnc_html * html,
|
||||
@ -93,8 +93,18 @@ void gnc_html_multipart_post_submit(gnc_html * html, const char * a,
|
||||
|
||||
URLType gnc_html_parse_url(gnc_html * html, const gchar * url,
|
||||
char ** url_location, char ** url_label);
|
||||
|
||||
/* some string coding/decoding routines */
|
||||
char * gnc_html_encode_string(const char * in);
|
||||
char * gnc_html_decode_string(const char * in);
|
||||
char * gnc_html_escape_newlines(const char * in);
|
||||
char * gnc_html_unescape_newlines(const char * in);
|
||||
|
||||
/* utilities for dealing with encoded argument strings for forms */
|
||||
char * gnc_html_pack_form_data(GHashTable * form_data);
|
||||
GHashTable * gnc_html_unpack_form_data(const char * encoding);
|
||||
void gnc_html_merge_form_data(GHashTable * fdata, const char * enc);
|
||||
void gnc_html_free_form_data(GHashTable * fdata);
|
||||
|
||||
gnc_html_history * gnc_html_get_history(gnc_html * html);
|
||||
GtkWidget * gnc_html_get_widget(gnc_html * html);
|
||||
|
@ -34,9 +34,12 @@
|
||||
#include <ghttp.h>
|
||||
#include <glib.h>
|
||||
#include <gtk/gtkmain.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gnc-http.h"
|
||||
#include "messages.h"
|
||||
|
||||
|
||||
struct _gnc_http {
|
||||
GList * requests;
|
||||
@ -80,10 +83,11 @@ gnc_http_cancel_requests(gnc_http * http) {
|
||||
for(current = http->requests; current; current = current->next) {
|
||||
if(current->data) {
|
||||
struct request_info * r = current->data;
|
||||
current->data = NULL;
|
||||
ghttp_request_destroy(r->request);
|
||||
r->request = NULL;
|
||||
g_free(r->uri);
|
||||
g_free(r);
|
||||
current->data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -96,14 +100,19 @@ gnc_http_cancel_requests(gnc_http * http) {
|
||||
static gint
|
||||
ghttp_check_callback(gpointer data) {
|
||||
gnc_http * http = data;
|
||||
GList * current;
|
||||
GList * current = NULL;
|
||||
ghttp_status status;
|
||||
struct request_info * req;
|
||||
struct request_info * req = NULL;
|
||||
|
||||
/* walk the request list to deal with any complete requests */
|
||||
for(current = http->requests; current; current = current->next) {
|
||||
req = current->data;
|
||||
|
||||
|
||||
if(!req) {
|
||||
printf(_("NULL request. \n"));
|
||||
continue;
|
||||
}
|
||||
|
||||
status = ghttp_process(req->request);
|
||||
switch(status) {
|
||||
case ghttp_done:
|
||||
@ -165,9 +174,9 @@ ghttp_check_callback(gpointer data) {
|
||||
static int
|
||||
gnc_http_certificate_check_cb(ghttp_request * req, X509 * cert,
|
||||
void * user_data) {
|
||||
printf("checking SSL certificate...");
|
||||
printf(_("checking SSL certificate..."));
|
||||
X509_print_fp(stdout, cert);
|
||||
printf(" ... done\n");
|
||||
printf(_(" ... done\n"));
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
@ -189,10 +198,9 @@ gnc_http_start_request(gnc_http * http, const gchar * uri,
|
||||
gnc_http_certificate_check_cb,
|
||||
(void *)http);
|
||||
#endif
|
||||
ghttp_set_uri(info->request, (char *)uri);
|
||||
ghttp_set_uri(info->request, strdup(uri));
|
||||
ghttp_set_header(info->request, http_hdr_User_Agent,
|
||||
PACKAGE "/" VERSION
|
||||
" (Financial Browser for Linux; http://gnucash.org)");
|
||||
strdup(PACKAGE "/" VERSION " ; http://gnucash.org"));
|
||||
ghttp_set_sync(info->request, ghttp_async);
|
||||
ghttp_set_type(info->request, ghttp_type_get);
|
||||
ghttp_prepare(info->request);
|
||||
@ -216,6 +224,7 @@ gnc_http_start_post(gnc_http * http, const char * uri,
|
||||
const char * data, int datalen,
|
||||
GncHTTPRequestCB cb, gpointer user_data) {
|
||||
struct request_info * info = g_new0(struct request_info, 1);
|
||||
char * new_body = malloc(datalen);
|
||||
|
||||
info->request = ghttp_request_new();
|
||||
info->uri = g_strdup (uri);
|
||||
@ -227,14 +236,14 @@ gnc_http_start_post(gnc_http * http, const char * uri,
|
||||
gnc_http_certificate_check_cb,
|
||||
(void *)http);
|
||||
#endif
|
||||
ghttp_set_uri(info->request, (char *)uri);
|
||||
ghttp_set_uri(info->request, strdup(uri));
|
||||
ghttp_set_header(info->request, http_hdr_User_Agent,
|
||||
PACKAGE "/" VERSION
|
||||
" (Financial Browser for Linux; http://gnucash.org)");
|
||||
strdup(PACKAGE "/" VERSION " ; 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, (char*)data, datalen);
|
||||
memcpy(new_body, data, datalen);
|
||||
ghttp_set_body(info->request, (char*)new_body, datalen);
|
||||
|
||||
ghttp_prepare(info->request);
|
||||
ghttp_process(info->request);
|
||||
|
640
src/gnome/gnc-network.c
Normal file
640
src/gnome/gnc-network.c
Normal file
@ -0,0 +1,640 @@
|
||||
/********************************************************************
|
||||
* gnc-network.c -- handlers for forms and objects relevant to *
|
||||
* GnuCash Network functions *
|
||||
* 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"
|
||||
|
||||
#include <gnome.h>
|
||||
#include <gtkhtml/gtkhtml.h>
|
||||
#include <gtkhtml/gtkhtml-embedded.h>
|
||||
|
||||
#include "global-options.h"
|
||||
#include "gnc-ui.h"
|
||||
#include "gnc-gpg.h"
|
||||
#include "gnc-html.h"
|
||||
#include "gnc-network.h"
|
||||
#include "query-user.h"
|
||||
#include "messages.h"
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* THIS IS PRIVACY-SENSITIVE CODE. The actions handled here are run
|
||||
* when gnucash needs to send HTML form information to a web server
|
||||
* (the "GnuCash Network") 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
|
||||
* only web server that will have such forms will be the GnuCash
|
||||
* Network server. Even if other hosts try to fool gnucash with
|
||||
* GnuCash Network submit actions, we will only ever submit to the
|
||||
* user's specified GnuCash Network server.
|
||||
*
|
||||
* 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 ("Enable GnuCash Network").
|
||||
*
|
||||
* 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. A server-side confirmation is probably enough, but
|
||||
* client-side confirm is better.
|
||||
*
|
||||
* 2. Do not 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. Always use the "GnuCash Network
|
||||
* server" from the global preferences option.
|
||||
********************************************************************/
|
||||
|
||||
static char * session_id = NULL;
|
||||
static char * gnc_passphrase = NULL;
|
||||
|
||||
static int
|
||||
gnc_network_get_handler(gnc_html * html,
|
||||
const char * method, const char * action,
|
||||
GHashTable * formdata);
|
||||
static int
|
||||
gnc_network_make_keypair_handler(gnc_html * html,
|
||||
GtkHTMLEmbedded * eb,
|
||||
gpointer data);
|
||||
|
||||
/********************************************************************
|
||||
* gnc_network_get/set_session_id
|
||||
********************************************************************/
|
||||
|
||||
char *
|
||||
gnc_network_get_session_id(void) {
|
||||
return session_id;
|
||||
}
|
||||
|
||||
void
|
||||
gnc_network_set_session_id(char * sid) {
|
||||
if(session_id) {
|
||||
g_free(session_id);
|
||||
}
|
||||
session_id = g_strdup(sid);
|
||||
}
|
||||
|
||||
char *
|
||||
gnc_network_get_uid(void) {
|
||||
SCM val = gnc_lookup_option("__gnc_network", "uid", gh_str02scm("0"));
|
||||
if(val != SCM_BOOL_F) {
|
||||
return gh_scm2newstr(val, NULL);
|
||||
}
|
||||
else {
|
||||
return strdup("");
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* gnc_network_build_url
|
||||
* build a full URL given the action
|
||||
********************************************************************/
|
||||
|
||||
char *
|
||||
gnc_network_build_url(const char * action) {
|
||||
char * server =
|
||||
gnc_lookup_string_option("Network", "GnuCash Network server",
|
||||
"www.gnumatic.com");
|
||||
char * retval = g_strconcat("http://", server, "/", action, NULL);
|
||||
g_free(server);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* gnc_network_get/free_passphrase
|
||||
********************************************************************/
|
||||
|
||||
static void
|
||||
get_pp_string_cb(char * string, gpointer data) {
|
||||
int l, i;
|
||||
|
||||
if(!data) return;
|
||||
if(!string) {
|
||||
*((char **)data) = NULL;
|
||||
}
|
||||
else {
|
||||
*((char **)data) = g_strdup(string);
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
gnc_network_ask_passphrase(const char * prompt) {
|
||||
char * pp = NULL;
|
||||
gint retval;
|
||||
GtkWidget * dlg =
|
||||
gnome_request_dialog(TRUE, prompt, "", 1024,
|
||||
get_pp_string_cb, (gpointer)&pp, NULL);
|
||||
retval = gnome_dialog_run_and_close(GNOME_DIALOG(dlg));
|
||||
if(retval == 0) {
|
||||
return pp;
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
gnc_network_get_passphrase(void) {
|
||||
if(gnc_passphrase) return gnc_passphrase;
|
||||
else {
|
||||
gnc_passphrase =
|
||||
gnc_network_ask_passphrase(_("Enter GnuCash Network passphrase:"));
|
||||
return gnc_passphrase;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* gnc_network_auth_handler
|
||||
* <object classid="gnc-network-auth"> handler. Sets the gnc-network
|
||||
* session ID from the encrypted "data" of the object.
|
||||
********************************************************************/
|
||||
|
||||
struct network_crypt_info {
|
||||
gnc_html * html;
|
||||
char * cryptext;
|
||||
char * cleartext;
|
||||
char * url;
|
||||
char * passphrase;
|
||||
int state;
|
||||
};
|
||||
|
||||
static void
|
||||
gnc_network_auth_crypt_cb(char * cleartext, gpointer data) {
|
||||
struct network_crypt_info * na = data;
|
||||
na->cleartext = cleartext;
|
||||
na->state = 2;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gnc_network_auth_check(gpointer data) {
|
||||
struct network_crypt_info * na = data;
|
||||
|
||||
switch(na->state) {
|
||||
case 0:
|
||||
/* get pp and start decryption */
|
||||
na->passphrase = gnc_network_get_passphrase();
|
||||
na->cleartext = NULL;
|
||||
na->state = 1;
|
||||
gnc_gpg_decrypt_async(na->cryptext, strlen(na->cryptext), na->passphrase,
|
||||
gnc_network_auth_crypt_cb, na);
|
||||
return TRUE;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
/* waiting for decryption */
|
||||
return TRUE;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
/* done.. take action */
|
||||
if(na->cleartext && (strlen(na->cleartext) > 0)) {
|
||||
gnc_network_set_session_id(na->cleartext);
|
||||
gnc_html_show_url(na->html, URL_TYPE_ACTION, na->url, NULL, 0);
|
||||
}
|
||||
else {
|
||||
gnc_warning_dialog(_("GnuCash Network authorization failed."));
|
||||
}
|
||||
/* clean up */
|
||||
g_free(na->cryptext);
|
||||
g_free(na->cleartext);
|
||||
g_free(na->url);
|
||||
g_free(na);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
gnc_network_auth_handler(gnc_html * html, GtkHTMLEmbedded * eb,
|
||||
gpointer data) {
|
||||
struct network_crypt_info * na = g_new0(struct network_crypt_info, 1);
|
||||
|
||||
na->html = html;
|
||||
na->cryptext = gnc_html_unescape_newlines(eb->data);
|
||||
na->cleartext = NULL;
|
||||
na->url = g_strdup(g_hash_table_lookup(eb->params, "url"));
|
||||
na->state = 0;
|
||||
|
||||
gtk_timeout_add(100, gnc_network_auth_check, na);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* gnc_network_crypt_handler : receives ascii-armored GPG
|
||||
* cryptext, decrypts it, and displays the result as HTML.
|
||||
********************************************************************/
|
||||
|
||||
static gboolean
|
||||
gnc_network_crypt_check(gpointer data) {
|
||||
struct network_crypt_info * na = data;
|
||||
|
||||
switch(na->state) {
|
||||
case 0:
|
||||
/* get pp and start decryption */
|
||||
na->passphrase = gnc_network_get_passphrase();
|
||||
na->cleartext = NULL;
|
||||
na->state = 1;
|
||||
gnc_gpg_decrypt_async(na->cryptext, strlen(na->cryptext), na->passphrase,
|
||||
gnc_network_auth_crypt_cb, na);
|
||||
return TRUE;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
/* waiting for decryption */
|
||||
return TRUE;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if(na->cleartext && (strlen(na->cleartext) > 0)) {
|
||||
gnc_html_show_data(na->html, na->cleartext, strlen(na->cleartext));
|
||||
}
|
||||
|
||||
/* clean up */
|
||||
g_free(na->cryptext);
|
||||
g_free(na->cleartext);
|
||||
g_free(na->url);
|
||||
g_free(na);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
gnc_network_crypt_handler(gnc_html * html, GtkHTMLEmbedded * eb,
|
||||
gpointer data) {
|
||||
struct network_crypt_info * na = g_new0(struct network_crypt_info, 1);
|
||||
|
||||
na->html = html;
|
||||
na->cryptext = gnc_html_unescape_newlines(eb->data);
|
||||
na->cleartext = NULL;
|
||||
na->url = g_strdup(g_hash_table_lookup(eb->params, "url"));
|
||||
na->state = 0;
|
||||
|
||||
gtk_timeout_add(100, gnc_network_crypt_check, na);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* gnc_make_keypair_handler : queries for a passphrase and
|
||||
* generates a keypair in the local keyring
|
||||
********************************************************************/
|
||||
|
||||
struct make_keypair_info {
|
||||
gnc_html * html;
|
||||
GtkHTMLEmbedded * eb;
|
||||
int state;
|
||||
char * username;
|
||||
char * uid;
|
||||
char * email;
|
||||
char * passphrase;
|
||||
char * next_action;
|
||||
char * cancel_action;
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
gnc_network_free_make_keypair_info(struct make_keypair_info * mk) {
|
||||
g_free(mk->username);
|
||||
g_free(mk->email);
|
||||
g_free(mk->uid);
|
||||
g_free(mk->passphrase);
|
||||
g_free(mk->cancel_action);
|
||||
g_free(mk->next_action);
|
||||
g_free(mk);
|
||||
}
|
||||
|
||||
static void
|
||||
gnc_network_make_keypair_cb(char * output, gpointer data) {
|
||||
struct make_keypair_info * mk = data;
|
||||
mk->state = 3;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gnc_network_make_keypair_check(gpointer data) {
|
||||
struct make_keypair_info * mk = data;
|
||||
char * verify_pp = NULL;
|
||||
GHashTable * fd = NULL;
|
||||
|
||||
switch(mk->state) {
|
||||
case 0:
|
||||
/* start: get first passphrase */
|
||||
mk->passphrase = gnc_network_ask_passphrase(_("Enter passphrase:"));
|
||||
|
||||
if(mk->passphrase) {
|
||||
mk->state = 1;
|
||||
return TRUE;
|
||||
}
|
||||
else {
|
||||
mk->state = 4;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
/* get another and check for equality */
|
||||
verify_pp = gnc_network_ask_passphrase(_("Verify passphrase:"));
|
||||
|
||||
if(verify_pp) {
|
||||
if(!strcmp(mk->passphrase, verify_pp)) {
|
||||
gnc_gpg_make_keypair_async(mk->username, mk->uid, mk->email,
|
||||
mk->passphrase,
|
||||
gnc_network_make_keypair_cb, mk);
|
||||
mk->state = 2;
|
||||
return TRUE;
|
||||
}
|
||||
else {
|
||||
gnc_error_dialog(_("Passphrases did not match."));
|
||||
gnc_network_make_keypair_handler(mk->html, mk->eb, data);
|
||||
gnc_network_free_make_keypair_info(mk);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
mk->state = 4;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
/* waiting for GPG to finish */
|
||||
return TRUE;
|
||||
|
||||
case 3:
|
||||
/* GPG is done making the key pair */
|
||||
fd = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
g_hash_table_insert(fd, g_strdup("uid"), mk->uid);
|
||||
g_hash_table_insert(fd, g_strdup("url"), mk->next_action);
|
||||
gnc_network_get_handler(mk->html, "get", "get", fd);
|
||||
gnc_html_free_form_data(fd);
|
||||
mk->uid = NULL;
|
||||
mk->next_action = NULL;
|
||||
gnc_network_free_make_keypair_info(mk);
|
||||
return FALSE;
|
||||
|
||||
case 4:
|
||||
/* cancel of passphrase get dialog */
|
||||
fd = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
g_hash_table_insert(fd, g_strdup("url"), mk->cancel_action);
|
||||
gnc_network_get_handler(mk->html, "get", "get", fd);
|
||||
gnc_html_free_form_data(fd);
|
||||
mk->cancel_action = NULL;
|
||||
gnc_network_free_make_keypair_info(mk);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
gnc_network_make_keypair_handler(gnc_html * html, GtkHTMLEmbedded * eb,
|
||||
gpointer data) {
|
||||
struct make_keypair_info * mk = g_new0(struct make_keypair_info, 1);
|
||||
mk->html = html;
|
||||
mk->eb = eb;
|
||||
mk->username = g_strdup(g_hash_table_lookup(eb->params, "username"));
|
||||
mk->uid = g_strdup(g_hash_table_lookup(eb->params, "uid"));
|
||||
mk->email = g_strdup(g_hash_table_lookup(eb->params, "email"));
|
||||
mk->next_action =
|
||||
g_strdup(g_hash_table_lookup(eb->params, "next-action"));
|
||||
mk->cancel_action =
|
||||
g_strdup(g_hash_table_lookup(eb->params, "cancel-action"));
|
||||
mk->passphrase = NULL;
|
||||
mk->state = 0;
|
||||
|
||||
gtk_timeout_add(100, gnc_network_make_keypair_check, mk);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* gnc_network_store_uid_handler : store a new GnuCash Network user id
|
||||
* (uid) locally.
|
||||
********************************************************************/
|
||||
|
||||
static int
|
||||
gnc_network_store_uid_handler(gnc_html * html, GtkHTMLEmbedded * eb,
|
||||
gpointer data) {
|
||||
int retval = TRUE;
|
||||
char * uid = g_hash_table_lookup(eb->params, "uid");
|
||||
gnc_set_option("__gnc_network", "uid", gh_str02scm(uid));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* gnc_network_get_with_auth_handler() fetch a gnucash network page
|
||||
* with an authorizing session ID. This either uses the current
|
||||
* session key or gets a new one if the session_id is null or expired.
|
||||
********************************************************************/
|
||||
|
||||
static int
|
||||
gnc_network_get_with_auth_handler(gnc_html * html,
|
||||
const char * method, const char * action,
|
||||
GHashTable * form_data) {
|
||||
char * new_action =
|
||||
gnc_network_build_url("gnc-network-auth.php");
|
||||
|
||||
g_hash_table_insert(form_data, g_strdup("sid"),
|
||||
g_strdup(gnc_network_get_session_id()));
|
||||
g_hash_table_insert(form_data, g_strdup("uid"),
|
||||
g_strdup(gnc_network_get_uid()));
|
||||
g_hash_table_insert(form_data, g_strdup("gnc_browser"),
|
||||
g_strdup("true"));
|
||||
|
||||
if(!strcasecmp(method, "get")) {
|
||||
gnc_html_generic_get_submit(html, new_action, form_data);
|
||||
}
|
||||
else {
|
||||
gnc_html_generic_post_submit(html, new_action, form_data);
|
||||
}
|
||||
g_free(new_action);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* gnc_network_get_handler
|
||||
* generic unauthorized 'get' for gnc-network server
|
||||
********************************************************************/
|
||||
|
||||
static int
|
||||
gnc_network_get_handler(gnc_html * html,
|
||||
const char * method, const char * action,
|
||||
GHashTable * form_data) {
|
||||
char * new_action =
|
||||
gnc_network_build_url("gnc-network-get.php");
|
||||
|
||||
g_hash_table_insert(form_data, g_strdup("uid"),
|
||||
g_strdup(gnc_network_get_uid()));
|
||||
g_hash_table_insert(form_data, g_strdup("gnc_browser"),
|
||||
g_strdup("true"));
|
||||
|
||||
/* gnc_html_merge_form_data(form_data, act_args); */
|
||||
if(!strcasecmp(method, "get")) {
|
||||
gnc_html_generic_get_submit(html, new_action, form_data);
|
||||
}
|
||||
else {
|
||||
gnc_html_generic_post_submit(html, new_action, form_data);
|
||||
}
|
||||
g_free(new_action);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* gnc_network_send_info_handler() : submit the form arguments
|
||||
* from 'encoding', appending additional arguments describing the
|
||||
* gnucash client: gnucash version string and some features.
|
||||
********************************************************************/
|
||||
|
||||
static int
|
||||
gnc_network_send_info_handler(gnc_html * html,
|
||||
const char * method, const char * action,
|
||||
GHashTable * form_data) {
|
||||
char * new_action = NULL;
|
||||
char * version_string = NULL;
|
||||
char * feature_string = NULL;
|
||||
|
||||
if(!method || !action
|
||||
|| strcmp(action, "get/info")) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
version_string = gh_scm2newstr(gh_eval_str("gnc:version"), NULL);
|
||||
|
||||
feature_string =
|
||||
g_strjoin(",",
|
||||
#if USE_GUPPI
|
||||
"guppi",
|
||||
#endif
|
||||
"gpg",
|
||||
#if HAVE_OPENSSL
|
||||
"openssl",
|
||||
#endif
|
||||
NULL);
|
||||
|
||||
g_hash_table_insert(form_data, g_strdup("gnc_browser"), g_strdup("true"));
|
||||
g_hash_table_insert(form_data, g_strdup("gnc_version"),
|
||||
g_strdup(version_string));
|
||||
g_hash_table_insert(form_data, g_strdup("gnc_features"),
|
||||
feature_string);
|
||||
free(version_string);
|
||||
|
||||
new_action = gnc_network_build_url("gnc-network-get.php");
|
||||
|
||||
if(!strcasecmp(method, "get")) {
|
||||
gnc_html_generic_get_submit(html, new_action, form_data);
|
||||
}
|
||||
else {
|
||||
gnc_html_generic_post_submit(html, new_action, form_data);
|
||||
}
|
||||
|
||||
g_free(new_action);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* gnc_network_send_pubkey_handler : send the public key as a multipart
|
||||
* POST submit
|
||||
********************************************************************/
|
||||
|
||||
static int
|
||||
gnc_network_submit_key_handler(gnc_html * html,
|
||||
const char * method, const char * action,
|
||||
GHashTable * form_data) {
|
||||
char * keyid = g_hash_table_lookup(form_data, "uid");
|
||||
char * submit = g_hash_table_lookup(form_data, "submit");
|
||||
char * keytext = NULL;
|
||||
char * new_action =
|
||||
gnc_network_build_url("gnc-network-get.php");
|
||||
|
||||
g_hash_table_insert(form_data, g_strdup("gnc_browser"), g_strdup("true"));
|
||||
|
||||
if(!strcmp(submit, "OK")) {
|
||||
/* get the public key */
|
||||
if(keyid) {
|
||||
keytext = gnc_gpg_export(keyid);
|
||||
}
|
||||
|
||||
/* stick it in the form data */
|
||||
g_hash_table_insert(form_data, g_strdup("pubkey"), keytext);
|
||||
|
||||
/* submit as a multipart form */
|
||||
gnc_html_multipart_post_submit(html, new_action, form_data);
|
||||
}
|
||||
else {
|
||||
/* don't export the pubkey, just submit as is. */
|
||||
gnc_html_generic_post_submit(html, new_action, form_data);
|
||||
}
|
||||
g_free(new_action);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* gnc_network_init()
|
||||
* set up GnuCash Network handlers
|
||||
********************************************************************/
|
||||
|
||||
void
|
||||
gnc_network_init(void) {
|
||||
/* <object> handlers */
|
||||
gnc_html_register_object_handler("gnc-network-auth",
|
||||
gnc_network_auth_handler);
|
||||
gnc_html_register_object_handler("gnc-network-crypt",
|
||||
gnc_network_crypt_handler);
|
||||
gnc_html_register_object_handler("gnc-make-keypair",
|
||||
gnc_network_make_keypair_handler);
|
||||
gnc_html_register_object_handler("gnc-store-uid",
|
||||
gnc_network_store_uid_handler);
|
||||
|
||||
/* <form> and gnc-action: handlers */
|
||||
gnc_html_register_action_handler("get",
|
||||
gnc_network_get_handler);
|
||||
gnc_html_register_action_handler("get/auth",
|
||||
gnc_network_get_with_auth_handler);
|
||||
gnc_html_register_action_handler("get/info",
|
||||
gnc_network_send_info_handler);
|
||||
gnc_html_register_action_handler("submit-key",
|
||||
gnc_network_submit_key_handler);
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
/********************************************************************
|
||||
* gnc-html-actions.h -- basic form submission actions *
|
||||
* Copyright (C) 2000 Bill Gribble <grib@billgribble.com> *
|
||||
* gnc-network.h -- handlers for forms and objects relevant to *
|
||||
* GnuCash Network functions *
|
||||
* 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 *
|
||||
@ -18,13 +19,19 @@
|
||||
* 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__
|
||||
#ifndef __GNC_NETWORK_H__
|
||||
#define __GNC_NETWORK_H__
|
||||
|
||||
#include "gnc-html.h"
|
||||
#include "config.h"
|
||||
|
||||
void gnc_html_actions_init(void);
|
||||
void gnc_network_init(void);
|
||||
|
||||
char * gnc_network_get_passphrase(void);
|
||||
char * gnc_network_ask_passphrase(const char * prompt);
|
||||
char * gnc_network_build_url(const char * gnc_action);
|
||||
char * gnc_network_get_session_id(void);
|
||||
void gnc_network_set_session_id(char * sid);
|
||||
char * gnc_network_get_uid(void);
|
||||
#endif
|
@ -46,13 +46,11 @@
|
||||
#include "gnc-component-manager.h"
|
||||
#include "gnc-engine-util.h"
|
||||
#include "gnc-splash.h"
|
||||
#include "gnc-html-actions.h"
|
||||
#include "gnc-network.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"
|
||||
@ -216,15 +214,12 @@ gnucash_ui_init(void)
|
||||
gtk_widget_set_default_visual (gdk_rgb_get_visual ());
|
||||
|
||||
/* load default HTML action handlers */
|
||||
gnc_html_actions_init();
|
||||
gnc_network_init();
|
||||
|
||||
#ifdef USE_GUPPI
|
||||
/* 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 */
|
||||
gnc_show_splash_screen ();
|
||||
|
@ -51,6 +51,11 @@
|
||||
((N_ "More on GnuCash") ""
|
||||
(((N_ "Hacking Documentation") "gnc-help:xacc-dochack.html" #f)
|
||||
((N_ "GNU GPL") "gnc-help:xacc-gpl.html" #f)))))
|
||||
((N_ "Support") ""
|
||||
(((N_ "Register GnuCash")
|
||||
"gnc-action:get?url=user-reg.php" #f)
|
||||
((N_ "GnuCash Network Home")
|
||||
"gnc-action:get/auth?url=gnc-network-home.php" #f)))
|
||||
((N_ "Guppi Demos") ""
|
||||
(((N_ "Pie chart") "gnc-help:guppi-pie-demo.html" #f)
|
||||
((N_ "Bar graph") "gnc-help:guppi-bar-demo.html" #f)
|
||||
|
@ -652,3 +652,8 @@ the current value of the path."
|
||||
(gnc:register-configuration-option
|
||||
(gnc:make-internal-option
|
||||
"__new_user" "first_startup" 1))
|
||||
|
||||
(gnc:register-configuration-option
|
||||
(gnc:make-internal-option
|
||||
"__gnc_network" "uid" ""))
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user