Factored out hublist handling from dolcon.c.
[doldaconnect.git] / clients / gtk2 / hublist.c
diff --git a/clients/gtk2/hublist.c b/clients/gtk2/hublist.c
new file mode 100644 (file)
index 0000000..7212146
--- /dev/null
@@ -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 <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <regex.h>
+#include <signal.h>
+#include <string.h>
+#include <stdarg.h>
+#include <gtk/gtk.h>
+#include <errno.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#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);
+}