From 0d04e87edb98d0a426db309038e9f288270abfbb Mon Sep 17 00:00:00 2001 From: Fredrik Tolf Date: Thu, 19 Jul 2007 06:36:58 +0200 Subject: [PATCH] Factored out hublist handling from dolcon.c. --- clients/gtk2/Makefile.am | 4 + clients/gtk2/dolcon.c | 389 ++------------------------------------------- clients/gtk2/dolcon.h | 36 +++++ clients/gtk2/hublist-old.c | 91 +++++++++++ clients/gtk2/hublist-xml.c | 215 +++++++++++++++++++++++++ clients/gtk2/hublist.c | 157 ++++++++++++++++++ clients/gtk2/hublist.h | 36 +++++ 7 files changed, 551 insertions(+), 377 deletions(-) create mode 100644 clients/gtk2/dolcon.h create mode 100644 clients/gtk2/hublist-old.c create mode 100644 clients/gtk2/hublist-xml.c create mode 100644 clients/gtk2/hublist.c create mode 100644 clients/gtk2/hublist.h diff --git a/clients/gtk2/Makefile.am b/clients/gtk2/Makefile.am index 67e7646..3dd77a3 100644 --- a/clients/gtk2/Makefile.am +++ b/clients/gtk2/Makefile.am @@ -4,6 +4,10 @@ app_DATA=dolcon.desktop endif dolcon_SOURCES= dolcon.c \ + hublist.c \ + hublist.h \ + hublist-xml.c \ + hublist-old.c \ progressbar.c \ progressbar.h diff --git a/clients/gtk2/dolcon.c b/clients/gtk2/dolcon.c index 9ea791d..02a2423 100644 --- a/clients/gtk2/dolcon.c +++ b/clients/gtk2/dolcon.c @@ -40,25 +40,16 @@ #include #include #include -#include #include -/* "Programming with libxml2 is like the thrilling embrace of an - * exotic strangler." - * --Me */ -#include -#include - #ifdef HAVE_CONFIG_H #include #endif +#include "dolcon.h" +#include "hublist.h" #include "progressbar.h" #define TRHISTSIZE 10 -#define PHO_INIT 0 -#define PHO_DATA 1 -#define PHO_EOF 2 -#define PHO_FINI 3 struct trdata { @@ -90,15 +81,11 @@ struct knownspeed GtkWidget *inpdialog; GtkListStore *fnmodel, *ulmodel, *dlmodel, *reslist; -int (*pubhubhandler)(int, char *, size_t *) = NULL; GtkTreeStore *srchmodel; GtkTreeModelFilter *srchmodelfilter; GtkTextTagTable *chattags; int dcfd = -1, gdkread = -1, gdkwrite = -1; -int pubhubfd = -1, pubhubtag = -1, filterpubhub = 0; int curchat = -1; -regex_t pubhubfilter; -pid_t pubhubproc = 0; char *pubhubaddr = NULL; char *connectas = NULL; char *dcserver = NULL; @@ -113,10 +100,6 @@ int numsizes = 0, numspeeds = 0, ksqueryseq = -1, ksquerytag = -1, lsrestag = -1 void dcfdcallback(gpointer data, gint source, GdkInputCondition condition); void srchstatupdate(void); -#define DCCHARSET "windows-1252" - -#define _(text) gettext(text) - #include "mainwnd.gtkh" #include "inpdialog.gtkh" #include "pref.gtkh" @@ -654,12 +637,6 @@ char *inputbox(char *title, char *prompt, char *def, int echo) } int msgbox(int type, int buttons, char *format, ...) -#if defined(__GNUC__) - __attribute__ ((format (printf, 3, 4))) -#endif -; - -int msgbox(int type, int buttons, char *format, ...) { GtkWidget *swnd; va_list args; @@ -1443,371 +1420,29 @@ void setpubhubmodel(GtkTreeModel *model, int sortcol, int numcols, int *cols, ch g_object_unref(sortmodel); } -xmlNodePtr findnode(xmlNodePtr node, char *name) -{ - for(; node != NULL; node = node->next) - { - if(!strcmp((char *)node->name, name)) - break; - } - return(node); -} - -int pubhubxmlhandler(int op, char *buf, size_t *len) -{ - static xmlParserCtxtPtr ctxt = NULL; - int i, match; - xmlNodePtr dr, r, cr, c, n; - int numcols, *cols, sortcol; - GType type, *types; - char **names, *name, *stype, *attr; - GtkListStore *model; - GtkTreeIter iter; - - numcols = 0; - names = NULL; - types = NULL; - switch(op) - { - case PHO_INIT: - break; - case PHO_DATA: - if(ctxt == NULL) { - ctxt = xmlCreatePushParserCtxt(NULL, NULL, buf, *len, pubhubaddr); - *len = 0; - if(ctxt == NULL) - return(1); - } else { - xmlParseChunk(ctxt, buf, *len, 0); - *len = 0; - } - break; - case PHO_EOF: - if(ctxt == NULL) - { - msgbox(GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _("A hub list could not be read from %s"), pubhubaddr); - break; - } - xmlParseChunk(ctxt, NULL, 0, 1); - if(!ctxt->wellFormed) - { - msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("The hub list at %s is not valid"), pubhubaddr); - break; - } - dr = r = cr = NULL; - dr = xmlDocGetRootElement(ctxt->myDoc); - if(dr != NULL) - r = findnode(dr->children, "Hubs"); - if(r != NULL) - cr = findnode(r->children, "Columns"); - if(cr == NULL) - { - msgbox(GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _("The hub list at %s cannot be understood"), pubhubaddr); - break; - } - for(c = findnode(cr->children, "Column"); c != NULL; c = findnode(c->next, "Column")) - { - name = (char *)xmlGetProp(c, (xmlChar *)"Name"); - stype = (char *)xmlGetProp(c, (xmlChar *)"Type"); - type = G_TYPE_INVALID; - if(stype != NULL) - { - if(!strcmp(stype, "string")) - type = G_TYPE_STRING; - else if(!strcmp(stype, "int")) - type = G_TYPE_INT; - else if(!strcmp(stype, "bytes")) - type = G_TYPE_INT64; - } - if((name != NULL) && (type != G_TYPE_INVALID)) - { - names = srealloc(names, (numcols + 1) * sizeof(*names)); - types = srealloc(types, (numcols + 1) * sizeof(*names)); - names[numcols] = sstrdup(name); - types[numcols] = type; - numcols++; - } - if(name != NULL) - xmlFree(name); - if(stype != NULL) - xmlFree(stype); - } - if(numcols == 0) - { - msgbox(GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _("The hub list at %s did not contain any columns"), pubhubaddr); - break; - } - for(i = 0; i < numcols; i++) - { - if(!strcmp(names[i], "Address")) - { - name = names[0]; - names[0] = names[i]; - names[i] = name; - type = types[0]; - types[0] = types[i]; - types[i] = type; - break; - } - } - if(i == numcols) - { - msgbox(GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _("The hub list at %s did not contain the address to any hubs"), pubhubaddr); - break; - } - model = gtk_list_store_newv(numcols, types); - for(n = findnode(r->children, "Hub"); n != NULL; n = findnode(n->next, "Hub")) - { - if(!xmlHasProp(n, (xmlChar *)"Address") || !xmlHasProp(n, (xmlChar *)"Name")) - continue; - if(filterpubhub) - { - match = 0; - attr = (char *)xmlGetProp(n, (xmlChar *)"Name"); - if(!regexec(&pubhubfilter, attr, 0, NULL, 0)) - match = 1; - xmlFree(attr); - if((attr = (char *)xmlGetProp(n, (xmlChar *)"Description")) != NULL) - { - if(!regexec(&pubhubfilter, attr, 0, NULL, 0)) - match = 1; - xmlFree(attr); - } - if(!match) - continue; - } - gtk_list_store_append(model, &iter); - for(i = 0; i < numcols; i++) - { - attr = (char *)xmlGetProp(n, (xmlChar *)names[i]); - if(attr != NULL) - { - if(types[i] == G_TYPE_STRING) - gtk_list_store_set(model, &iter, i, attr, -1); - else if(types[i] == G_TYPE_INT) - gtk_list_store_set(model, &iter, i, atoi(attr), -1); - else if(types[i] == G_TYPE_INT64) - gtk_list_store_set(model, &iter, i, strtoll(attr, NULL, 0), -1); - xmlFree(attr); - } - } - } - cols = smalloc((numcols - 1) * sizeof(*cols)); - for(i = 1; i < numcols; i++) - cols[i - 1] = i; - sortcol = 0; - for(i = 0; i < numcols; i++) - { - if(!strcmp(names[i], "Users")) - sortcol = i; - } - setpubhubmodel(GTK_TREE_MODEL(model), sortcol, numcols - 1, cols, names + 1); - free(cols); - g_object_unref(model); - break; - case PHO_FINI: - if(ctxt != NULL) - { - if(ctxt->myDoc != NULL) - xmlFreeDoc(ctxt->myDoc); - xmlFreeParserCtxt(ctxt); - ctxt = NULL; - } - break; - } - if(numcols != 0) - { - for(i = 0; i < numcols; i++) - free(names[i]); - free(names); - free(types); - } - return(0); -} - -int pubhuboldhandler(int op, char *buf, size_t *len) -{ - static GtkListStore *model = NULL; - int i; - char *p, *p2; - wchar_t *wbuf; - char *fields[4], *names[3]; - int cols[3]; - GtkTreeIter iter; - - switch(op) - { - case PHO_INIT: - model = gtk_list_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT); - break; - case PHO_DATA: - while((p = memchr(buf, '\n', *len)) != NULL) - { - *(p++) = 0; - for(i = 0, p2 = buf; i < 4; i++) { - fields[i] = p2; - if((p2 = strchr(p2, '|')) == NULL) - break; - *(p2++) = 0; - } - if(i == 4) { - for(i = 0; i < 4; i++) { - if((wbuf = icsmbstowcs(fields[i], DCCHARSET, NULL)) == NULL) { - fields[i] = sstrdup(_("(Invalid character)")); - } else { - if((fields[i] = icwcstombs(wbuf, "UTF-8")) == NULL) - break; - } - } - if(i == 4) { - if(!filterpubhub || !regexec(&pubhubfilter, fields[0], 0, NULL, 0) || !regexec(&pubhubfilter, fields[2], 0, NULL, 0)) { - gtk_list_store_append(model, &iter); - gtk_list_store_set(model, &iter, 0, fields[1], 1, fields[0], 2, fields[2], 3, atoi(fields[3]), -1); - } - } - for(i--; i >= 0; i--) - free(fields[i]); - } - memmove(buf, p, *len -= p - buf); - } - break; - case PHO_EOF: - cols[0] = 3; names[0] = _("# users"); - cols[1] = 1; names[1] = _("Name"); - cols[2] = 2; names[2] = _("Description"); - setpubhubmodel(GTK_TREE_MODEL(model), 3, 3, cols, names); - break; - case PHO_FINI: - if(model != NULL) - g_object_unref(model); - model = NULL; - break; - } - return(0); -} - -void pubhubfdcallback(gpointer data, gint source, GdkInputCondition condition) -{ - static char buf[65536]; - static size_t bufpos = 0; - int ret, reset; - - if(!(condition & GDK_INPUT_READ)) - return; - if(bufpos == sizeof(buf)) - bufpos = 0; - ret = read(pubhubfd, buf + bufpos, sizeof(buf) - bufpos); - reset = 0; - if(ret <= 0) - { - if(ret < 0) - msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Could not read from public hub listing process: %s"), strerror(errno)); - else - pubhubhandler(PHO_EOF, NULL, NULL); - reset = 1; - } else { - bufpos += ret; - if(pubhubhandler(PHO_DATA, buf, &bufpos)) - reset = 1; - } - if(reset) - { - pubhubhandler(PHO_FINI, NULL, NULL); - pubhubhandler = NULL; - gdk_input_remove(pubhubtag); - close(pubhubfd); - kill(pubhubproc, SIGINT); - pubhubfd = pubhubtag = -1; - pubhubproc = 0; - bufpos = 0; - if(filterpubhub) - { - regfree(&pubhubfilter); - filterpubhub = 0; - } - } -} - void cb_main_pubhubfilter_activate(GtkWidget *widget, gpointer data) { - int pipe1[2], pipe2[2]; - int len, err; - const char *buf, *p; + int err; + const char *buf; char errbuf[1024]; + regex_t *filter; - if(pubhubtag >= 0) - gdk_input_remove(pubhubtag); - if(pubhubfd >= 0) - close(pubhubfd); - if(pubhubproc > 0) - kill(pubhubproc, SIGINT); - if(pubhubhandler != NULL) - { - pubhubhandler(PHO_FINI, NULL, NULL); - pubhubhandler = NULL; - } - if(filterpubhub) - { - regfree(&pubhubfilter); - filterpubhub = 0; - } buf = gtk_entry_get_text(GTK_ENTRY(main_pubhubfilter)); if(*buf) { - if((err = regcomp(&pubhubfilter, buf, REG_EXTENDED | REG_ICASE | REG_NOSUB)) != 0) + filter = smalloc(sizeof(*filter)); + if((err = regcomp(filter, buf, REG_EXTENDED | REG_ICASE | REG_NOSUB)) != 0) { - regerror(err, &pubhubfilter, errbuf, sizeof(errbuf)); + regerror(err, filter, errbuf, sizeof(errbuf)); msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Could not compile regex: %s", errbuf); - regfree(&pubhubfilter); - filterpubhub = 0; + regfree(filter); + free(filter); return; } - filterpubhub = 1; - } - pipe(pipe1); - if((pubhubproc = fork()) == 0) - { - dup2(pipe1[1], 1); - close(pipe1[0]); - close(pipe1[1]); - execlp("wget", "wget", "-qO", "-", pubhubaddr, NULL); - perror("wget"); - exit(127); - } - close(pipe1[1]); - pubhubfd = pipe1[0]; - len = strlen(pubhubaddr); - p = pubhubaddr + len; - if((len > 4) && !strncmp(p - 4, ".bz2", 4)) - { - p -= 4; - len -= 4; - pipe(pipe2); - if(fork() == 0) - { - dup2(pipe1[0], 0); - dup2(pipe2[1], 1); - close(pipe1[0]); - close(pipe2[0]); - close(pipe2[1]); - execlp("bzcat", "bzcat", NULL); - perror("bzcat"); - exit(127); - } - close(pipe1[0]); - close(pipe2[1]); - pubhubfd = pipe2[0]; - } - if((len > 4) && !strncmp(p - 4, ".xml", 4)) - { - p -= 4; - len -= 4; - pubhubhandler = pubhubxmlhandler; } else { - pubhubhandler = pubhuboldhandler; + filter = NULL; } - pubhubhandler(PHO_INIT, NULL, NULL); - pubhubtag = gdk_input_add(pubhubfd, GDK_INPUT_READ, pubhubfdcallback, NULL); + fetchhublist(pubhubaddr, filter); } void cb_main_dcnctbtn_clicked(GtkWidget *widget, gpointer data) diff --git a/clients/gtk2/dolcon.h b/clients/gtk2/dolcon.h new file mode 100644 index 0000000..00d2424 --- /dev/null +++ b/clients/gtk2/dolcon.h @@ -0,0 +1,36 @@ +/* + * Dolda Connect - Modular multiuser Direct Connect-style client + * Copyright (C) 2007 Fredrik Tolf (fredrik@dolda2000.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _DOLCON_H +#define _DOLCON_H + +#include + +#define _(text) gettext(text) +#define DCCHARSET "windows-1252" + +int msgbox(int type, int buttons, char *format, ...) +#if defined(__GNUC__) + __attribute__ ((format (printf, 3, 4))) +#endif +; + +void setpubhubmodel(GtkTreeModel *model, int sortcol, int numcols, int *cols, char **names); + +#endif diff --git a/clients/gtk2/hublist-old.c b/clients/gtk2/hublist-old.c new file mode 100644 index 0000000..83da7fc --- /dev/null +++ b/clients/gtk2/hublist-old.c @@ -0,0 +1,91 @@ +/* + * Dolda Connect - Modular multiuser Direct Connect-style client + * Copyright (C) 2007 Fredrik Tolf (fredrik@dolda2000.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif +#include "dolcon.h" +#include "hublist.h" + +int pubhuboldhandler(int op, char *buf, size_t len) +{ + static GtkListStore *model = NULL; + int i; + char *p, *p2; + wchar_t *wbuf; + char *fields[4], *names[3]; + int cols[3]; + GtkTreeIter iter; + + switch(op) + { + case PHO_INIT: + model = gtk_list_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT); + break; + case PHO_DATA: + p = buf; + while((p = memchr(p, '\n', len)) != NULL) + { + *(p++) = 0; + for(i = 0, p2 = buf; i < 4; i++) { + fields[i] = p2; + if((p2 = strchr(p2, '|')) == NULL) + break; + *(p2++) = 0; + } + if(i == 4) { + for(i = 0; i < 4; i++) { + if((wbuf = icsmbstowcs(fields[i], DCCHARSET, NULL)) == NULL) { + fields[i] = sstrdup(_("(Invalid character)")); + } else { + if((fields[i] = icwcstombs(wbuf, "UTF-8")) == NULL) + break; + } + } + if(i == 4) { + if(validhub(fields[0], fields[2], NULL)) { + gtk_list_store_append(model, &iter); + gtk_list_store_set(model, &iter, 0, fields[1], 1, fields[0], 2, fields[2], 3, atoi(fields[3]), -1); + } + } + for(i--; i >= 0; i--) + free(fields[i]); + } + } + return(p - buf); + break; + case PHO_EOF: + cols[0] = 3; names[0] = _("# users"); + cols[1] = 1; names[1] = _("Name"); + cols[2] = 2; names[2] = _("Description"); + setpubhubmodel(GTK_TREE_MODEL(model), 3, 3, cols, names); + break; + case PHO_FINI: + if(model != NULL) + g_object_unref(model); + model = NULL; + break; + } + return(0); +} diff --git a/clients/gtk2/hublist-xml.c b/clients/gtk2/hublist-xml.c new file mode 100644 index 0000000..e67f717 --- /dev/null +++ b/clients/gtk2/hublist-xml.c @@ -0,0 +1,215 @@ +/* + * Dolda Connect - Modular multiuser Direct Connect-style client + * Copyright (C) 2007 Fredrik Tolf (fredrik@dolda2000.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include + +/* "Programming with libxml2 is like the thrilling embrace of an + * exotic strangler." + * --Me */ +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif +#include "dolcon.h" +#include "hublist.h" + +static xmlNodePtr findnode(xmlNodePtr node, char *name) +{ + for(; node != NULL; node = node->next) + { + if(!strcmp((char *)node->name, name)) + break; + } + return(node); +} + +static int checkvalid(xmlNodePtr n) +{ + int match; + char *name, *descr; + + name = (char *)xmlGetProp(n, (xmlChar *)"Name"); + descr = (char *)xmlGetProp(n, (xmlChar *)"Description"); + match = validhub(name, descr, NULL); + xmlFree(name); + if(descr != NULL) + xmlFree(descr); + return(match); +} + +int pubhubxmlhandler(int op, char *buf, size_t len) +{ + static xmlParserCtxtPtr ctxt = NULL; + int i; + xmlNodePtr dr, r, cr, c, n; + int numcols, *cols, sortcol; + GType type, *types; + char **names, *name, *stype, *attr; + GtkListStore *model; + GtkTreeIter iter; + + numcols = 0; + names = NULL; + types = NULL; + switch(op) + { + case PHO_INIT: + break; + case PHO_DATA: + if(ctxt == NULL) { + ctxt = xmlCreatePushParserCtxt(NULL, NULL, buf, len, NULL); + if(ctxt == NULL) + return(-1); + } else { + xmlParseChunk(ctxt, buf, len, 0); + } + return(len); + case PHO_EOF: + if(ctxt == NULL) + { + msgbox(GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _("A hub list could not be read from the server")); + break; + } + xmlParseChunk(ctxt, NULL, 0, 1); + if(!ctxt->wellFormed) + { + msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("The hub list is not valid")); + break; + } + dr = r = cr = NULL; + dr = xmlDocGetRootElement(ctxt->myDoc); + if(dr != NULL) + r = findnode(dr->children, "Hubs"); + if(r != NULL) + cr = findnode(r->children, "Columns"); + if(cr == NULL) + { + msgbox(GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _("The hub list cannot be understood")); + break; + } + for(c = findnode(cr->children, "Column"); c != NULL; c = findnode(c->next, "Column")) + { + name = (char *)xmlGetProp(c, (xmlChar *)"Name"); + stype = (char *)xmlGetProp(c, (xmlChar *)"Type"); + type = G_TYPE_INVALID; + if(stype != NULL) + { + if(!strcmp(stype, "string")) + type = G_TYPE_STRING; + else if(!strcmp(stype, "int")) + type = G_TYPE_INT; + else if(!strcmp(stype, "bytes")) + type = G_TYPE_INT64; + } + if((name != NULL) && (type != G_TYPE_INVALID)) + { + names = srealloc(names, (numcols + 1) * sizeof(*names)); + types = srealloc(types, (numcols + 1) * sizeof(*names)); + names[numcols] = sstrdup(name); + types[numcols] = type; + numcols++; + } + if(name != NULL) + xmlFree(name); + if(stype != NULL) + xmlFree(stype); + } + if(numcols == 0) + { + msgbox(GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _("The hub list did not contain any columns")); + break; + } + for(i = 0; i < numcols; i++) + { + if(!strcmp(names[i], "Address")) + { + name = names[0]; + names[0] = names[i]; + names[i] = name; + type = types[0]; + types[0] = types[i]; + types[i] = type; + break; + } + } + if(i == numcols) + { + msgbox(GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _("The hub list did not contain the address to any hubs")); + break; + } + model = gtk_list_store_newv(numcols, types); + for(n = findnode(r->children, "Hub"); n != NULL; n = findnode(n->next, "Hub")) + { + if(!xmlHasProp(n, (xmlChar *)"Address") || !xmlHasProp(n, (xmlChar *)"Name")) + continue; + if(!checkvalid(n)) + continue; + gtk_list_store_append(model, &iter); + for(i = 0; i < numcols; i++) + { + attr = (char *)xmlGetProp(n, (xmlChar *)names[i]); + if(attr != NULL) + { + if(types[i] == G_TYPE_STRING) + gtk_list_store_set(model, &iter, i, attr, -1); + else if(types[i] == G_TYPE_INT) + gtk_list_store_set(model, &iter, i, atoi(attr), -1); + else if(types[i] == G_TYPE_INT64) + gtk_list_store_set(model, &iter, i, strtoll(attr, NULL, 0), -1); + xmlFree(attr); + } + } + } + cols = smalloc((numcols - 1) * sizeof(*cols)); + for(i = 1; i < numcols; i++) + cols[i - 1] = i; + sortcol = 0; + for(i = 0; i < numcols; i++) + { + if(!strcmp(names[i], "Users")) + sortcol = i; + } + setpubhubmodel(GTK_TREE_MODEL(model), sortcol, numcols - 1, cols, names + 1); + free(cols); + g_object_unref(model); + break; + case PHO_FINI: + if(ctxt != NULL) + { + if(ctxt->myDoc != NULL) + xmlFreeDoc(ctxt->myDoc); + xmlFreeParserCtxt(ctxt); + ctxt = NULL; + } + break; + } + if(numcols != 0) + { + for(i = 0; i < numcols; i++) + free(names[i]); + free(names); + free(types); + } + return(0); +} diff --git a/clients/gtk2/hublist.c b/clients/gtk2/hublist.c new file mode 100644 index 0000000..7212146 --- /dev/null +++ b/clients/gtk2/hublist.c @@ -0,0 +1,157 @@ +/* + * Dolda Connect - Modular multiuser Direct Connect-style client + * Copyright (C) 2007 Fredrik Tolf (fredrik@dolda2000.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif +#include "dolcon.h" +#include "hublist.h" + +static regex_t *filter = NULL; +static pid_t fetchpid = 0; +static int listfd = -1; +static int iotag = -1; +static int (*handler)(int, char *, size_t) = NULL; +static char readbuf[65536]; +static off_t bufpos = 0; + +void aborthublist(void) +{ + if(fetchpid > 0) { + gdk_input_remove(iotag); + iotag = -1; + close(listfd); + listfd = -1; + kill(fetchpid, SIGINT); + fetchpid = 0; + if(filter != NULL) { + regfree(filter); + free(filter); + filter = NULL; + } + if(handler != NULL) { + handler(PHO_FINI, NULL, 0); + handler = NULL; + } + } +} + +int validhub(char *field, ...) +{ + int match; + va_list args; + + if(filter == NULL) + return(1); + match = 0; + va_start(args, field); + do { + if(!regexec(filter, field, 0, NULL, 0)) { + match = 1; + break; + } + } while((field = va_arg(args, char *)) != NULL); + va_end(args); + return(match); +} + +static void readcb(gpointer data, gint source, GdkInputCondition cond) +{ + int ret; + + if(!(cond & GDK_INPUT_READ)) + return; + if(bufpos == sizeof(readbuf)) + bufpos = 0; + ret = read(listfd, readbuf + bufpos, sizeof(readbuf) - bufpos); + if(ret <= 0) { + if(ret < 0) + msgbox(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Could not read from public hub listing process: %s"), strerror(errno)); + else + handler(PHO_EOF, NULL, 0); + aborthublist(); + } else { + bufpos += ret; + if((ret = handler(PHO_DATA, readbuf, (size_t)bufpos)) < 0) + aborthublist(); + else + memmove(readbuf, readbuf + ret, bufpos -= ret); + } +} + +void fetchhublist(char *url, regex_t *flt) +{ + int pfd[2]; + int len; + char *p; + + aborthublist(); + filter = flt; + pipe(pfd); + if((fetchpid = fork()) == 0) { + dup2(pfd[1], 1); + close(pfd[0]); + close(pfd[1]); + execlp("wget", "wget", "-qO", "-", url, NULL); + perror("wget"); + exit(127); + } + close(pfd[1]); + listfd = pfd[0]; + len = strlen(url); + p = url + len; + if((len > 4) && !strncmp(p - 4, ".bz2", 4)) { + p -= 4; + len -= 4; + pipe(pfd); + if(fork() == 0) { + dup2(listfd, 0); + dup2(pfd[1], 1); + close(listfd); + close(pfd[0]); + close(pfd[1]); + execlp("bzcat", "bzcat", NULL); + perror("bzcat"); + exit(127); + } + close(listfd); + close(pfd[1]); + listfd = pfd[0]; + } + if((len > 4) && !strncmp(p - 4, ".xml", 4)) { + p -= 4; + len -= 4; + handler = pubhubxmlhandler; + } else { + handler = pubhuboldhandler; + } + bufpos = 0; + handler(PHO_INIT, NULL, 0); + iotag = gdk_input_add(listfd, GDK_INPUT_READ, readcb, NULL); +} diff --git a/clients/gtk2/hublist.h b/clients/gtk2/hublist.h new file mode 100644 index 0000000..5c09d55 --- /dev/null +++ b/clients/gtk2/hublist.h @@ -0,0 +1,36 @@ +/* + * Dolda Connect - Modular multiuser Direct Connect-style client + * Copyright (C) 2007 Fredrik Tolf (fredrik@dolda2000.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _HUBLIST_H +#define _HUBLIST_H + +#include + +#define PHO_INIT 0 +#define PHO_DATA 1 +#define PHO_EOF 2 +#define PHO_FINI 3 + +int validhub(char *field, ...); +void fetchhublist(char *url, regex_t *flt); + +int pubhubxmlhandler(int op, char *buf, size_t len); +int pubhuboldhandler(int op, char *buf, size_t len); + +#endif -- 2.11.0