Excuse me the triple mail. I am very sorry for the problems this mail causes Hello and great work. Here i resend 2 patches related to DPI infrastructure. The first patch (dpid_services_support.diff) add the service concept to dpid (like docs sugest) so DPIs names are not related to services names asked by dillo, more than a DPI can serve a service and various DPIs can be installed to serve one service. The patch add new configuration lines in dpidrc, but can work without changes in dpidrc. (backward compatible) The lines in dpidrc have the form: service_name=ending_part_of_path_to_DPI User DPIs are preferred to system DPIs. Example: bookmarks=/bookmarks.dpi cookies=cookies/cookies.dpi downloads=downloads/downloads.dpi file=file/file.dpi ftp=ftp/ftp.filter.dpi https=https/https.filter.dpi data=datauri/datauri.filter.dpi hello=hello/hello.filter.dpi service names ending in '*' match a service asked by dillo starting with the text before the '*' and that not match other service names Example: car=car.dpi cab=cab.dpi ca*=a.dpi a.dpi is used only if dillo ask for a service that start with ca but is not car or cab To test the patch add next line to dpidrc: test=hello/hello.filter.dpi and use the url dpi:/test/ The second path (proto_services.diff) removes ad-hoc bindings for protocols DPIs in dillo. It uses services for protocols handled externaly (internal protocols: http and about; external: file, ftp, https and data). With this 2 features a protocol DPI (mms:, ed2k:, ...) can be programed without changes to dillo. The service names have the form proto.protocol_name. The lines below must be added to dpidrc and dpid need to be patched with first path (dpid_services_support.diff) so protocols works as before. (NOT backward compatible) proto.file=file/file.dpi proto.ftp=ftp/ftp.filter.dpi proto.https=https/https.filter.dpi proto.data=datauri/datauri.filter.dpi With the next line not handled protocols can return an error, a page to download new DPIs or search new protocol DPIs in dillo page using a DPI: proto.*=proto/unknown.filter.dpi This scrip mimics dillo operation #!/bin/sh # read dillo open url command read -d'>' dpip_tag echo "<dpi cmd='send_status_message' msg='ERROR: unsupported protocol' '>" I have rediscover the dpid bug (without and with pach) that ignore a DPI installed in user and system DPI_dirs at the same time. It is not solved so care about it. Diego. ----------- dpid_services_support.diff --------------------------------------------------------- diff -pru dillo2/dpid/dpid.c g/dpid/dpid.c --- dillo2/dpid/dpid.c 2007-10-14 02:09:40.000000000 +0200 +++ g/dpid/dpid.c 2007-11-24 18:19:36.000000000 +0100 @@ -23,6 +23,7 @@ #include <sys/stat.h> #include <sys/wait.h> #include <unistd.h> +#include <ctype.h> #include "dpid_common.h" #include "dpid.h" #include "dpi.h" @@ -138,6 +139,20 @@ void free_plugin_list(struct dp **dpi_at *dpi_attr_list_ptr = NULL; } +/*! Free memory used by the services list + */ +void free_services_list(Dlist *s_list) +{ + int i = 0; + struct service *s; + + for (i=0; i < dList_length(s_list) ; i++) { + s = dList_nth_data(s_list, i); + dFree(s->name); + } +// dList_free(s_list); +} + /*! \todo * Remove terminator and est_terminator unless we really want to clean up * on abnormal exit. @@ -409,6 +424,145 @@ int register_all(struct dp **attlist) return (snum); } +/* + * Compare two FileInfo pointers + * This function is used for sorting directories + */ +static int services_alpha_comp(const struct service *s1, const struct service *s2) +{ + int t; + + t=strcmp(s1->name, s2->name); + if (t>0) + return -1; + else if (t<0) + return 1; + + return 0; +} + +/*! Add services reading a dpidrc file + * each non empty or commented line has the form + * service = path_relative_to_dpidir + * \Return: + * \li Returns number of available services on success + * \li -1 on failure + */ +int fill_services_list(struct dp **attlist, int numdpis, Dlist *services_list) +{ + FILE *dpidrc_stream; + char *line = NULL; + int line_num = 0; + char *p; + char *service, *path; + int i; + struct service *s; + char *user_dpidir = NULL, *sys_dpidir = NULL, *dpidrc = NULL; + + user_dpidir = dStrconcat(dGethomedir(), "/", dotDILLO_DPI, NULL); + if (access(user_dpidir, F_OK) == -1) { + /* no dpis in user's space */ + dFree(user_dpidir); + user_dpidir = NULL; + } + dpidrc = dStrconcat(dGethomedir(), "/", dotDILLO_DPIDRC, NULL); + if (access(dpidrc, F_OK) == -1) { + dFree(dpidrc); + dpidrc = dStrdup(DPIDRC_SYS); + if (access(dpidrc, F_OK) == -1) { + dFree(dpidrc); + dpidrc = NULL; + } + } + if (!dpidrc || (sys_dpidir = get_dpi_dir(dpidrc)) == NULL) + sys_dpidir = NULL; + + if (!user_dpidir && !sys_dpidir) { + ERRMSG("fill_services_list", "Fatal error ", 0); + fprintf(stderr, "\n - Can't find the directory for dpis.\n"); + exit(1); + } + + if ((dpidrc_stream = fopen(dpidrc, "r")) == NULL) { + ERRMSG("fill_services_list", "popen failed", errno); + dFree(dpidrc); + dFree(sys_dpidir); + dFree(user_dpidir); + return (-1); + } + + /* dpidrc parser loop */ + while ((line = dGetline(dpidrc_stream)) != NULL) { + i++; + /* ignore start spaces, commented and empty lines */ + dStrstrip(line); + if (*line == '#' || *line == '\0') + continue; + + service = line; + if ((path = strchr(line, '=')) == NULL) { + printf("malformed line in %s at %d: \'=\' not found\n", dpidrc, line_num); + continue; + } + *path = '\0'; + path++; + + dStrstrip(service); + /* check that service name do not contains spaces */ + if (strchr(service, ' ') != NULL) { + printf("malformed line in %s at %d: service contains spaces\n", dpidrc, i); + continue; + } + if (strlen(service) < 2) { + printf("malformed line in %s at %d: service name too sort\n", dpidrc, i); + continue; + } + /* ignore dpi_dir silently */ + if (strcmp(service, "dpi_dir") == 0) + continue; + + dStrstrip(path); + /* process quotes */ + if (*path == '\"' || *path == '\'') { + p = strrchr(path + 1, *path); + if (p == NULL) { + printf("malformed line in %s at %d: unpaired \'%c\'\n", dpidrc, i, *path); + continue; + } else if (p[1] != '\0') { + printf("malformed line in %s at %d: garbage after \'%c\'\n", dpidrc, i, *path); + continue; + } + path++; + } + + s = dNew(struct service, 1); + /* init services list entry */ + s->name = dStrdup(service); + s->dp_index = -1; + + dList_append(services_list, s); + /* search the dpi for a service by its path */ + for (i = 0; i < numdpis; i++) + if ((p = strstr((*attlist)[i].path, path)) && *(p - 1) == '/' && + strlen(p) == strlen(path)) + break; + /* if the dpi exist bind service and dpi */ + if (i < numdpis) + s->dp_index = i; + dFree(line); + } + fclose(dpidrc_stream); + + dList_sort(services_list, (dCompareFunc)services_alpha_comp); + + dFree(dpidrc); + dFree(sys_dpidir); + dFree(user_dpidir); + + return (dList_length(services_list)); +} + + /*! Initialise the service request socket * \Return: * \li Number of sockets (1 == success) @@ -668,11 +822,13 @@ int register_all_cmd(char *sockdir) stop_active_dpis(dpi_attr_list, numdpis); rm_dpi_sockets(dpi_attr_list, numdpis); free_plugin_list(&dpi_attr_list, numdpis); + free_services_list(services_list); numdpis = 0; numsocks = 1; /* the srs socket */ FD_ZERO(&sock_set); FD_SET(srs, &sock_set); numdpis = register_all(&dpi_attr_list); + fill_services_list(&dpi_attr_list, numdpis, services_list); numsocks = init_all_dpi_sockets(dpi_attr_list, sockdir); return (numdpis); } @@ -697,6 +853,20 @@ char *get_message(int sock, char *dpi_ta return (msg); } +int service_match(const struct service *A, const char *B) +{ + int A_len, B_len, len; + + A_len = strlen(A->name); + B_len = strlen(B); + len = MAX (A_len, B_len); + + if (A->name[A_len - 1] == '*') + len = A_len - 1; + + return(dStrncasecmp(A->name, B, len)); +} + /*! * Send socket path that matches dpi_id to client */ @@ -705,12 +875,18 @@ void send_sockpath(int sock, char *dpi_t int i; char *dpi_id; char *d_cmd; + struct service *serv; dReturn_if_fail((dpi_id = get_message(sock, dpi_tag)) != NULL); - for (i = 0; i < numdpis; i++) - if (strstr(dpi_attr_list[i].id, dpi_id)) - break; + serv = dList_find_custom(services_list, dpi_id, (dCompareFunc)service_match); + + if (serv == NULL || (i = serv->dp_index) == -1) + for (i = 0; i < numdpis; i++) + if (!strncmp(dpi_attr_list[i].id, dpi_id, + dpi_attr_list[i].id - strchr(dpi_attr_list[i].id, '.'))) + break; + if (i < numdpis) { /* found */ if (access(dpi_attr_list[i].path, F_OK) == -1) { diff -pru dillo2/dpid/dpid.h g/dpid/dpid.h --- dillo2/dpid/dpid.h 2007-10-07 00:36:34.000000000 +0200 +++ g/dpid/dpid.h 2007-11-24 18:17:14.000000000 +0100 @@ -45,6 +45,13 @@ struct dp { int filter; }; +/*! bind dpi with service + */ +struct service { + char *name; + int dp_index; +}; + /*! Number of available plugins */ int numdpis; @@ -54,6 +61,9 @@ int numsocks; /*! State information for each plugin. */ struct dp *dpi_attr_list; +/*! service served for each plugin */ +Dlist *services_list; + /*! Set of sockets watched for connections */ fd_set sock_set; @@ -70,6 +80,8 @@ void free_dpi_attr(struct dp *dpi_attr); void free_plugin_list(struct dp **dpi_attr_list_ptr, int numdpis); +void free_services_list(Dlist *s_list); + enum file_type get_file_type(char *file_name); int get_dpi_attr(char *dpi_dir, char *service, struct dp *dpi_attr); @@ -78,6 +90,10 @@ int register_service(struct dp *dpi_attr int register_all(struct dp **attlist); +static int services_alpha_comp(const struct service *s1, const struct service *s2); + +int fill_services_list(struct dp **attlist, int numdpis, Dlist *services_list); + int init_srs_socket(char *sockdir); int init_dpi_socket(struct dp *dpi_attr, char *sockdir); @@ -98,6 +114,8 @@ int register_all_cmd(char *sockdir); char *get_message(int sock, char *dpi_tag); +int service_match(const struct service *A, const char *B); + void send_sockpath(int sock, char * dpi_tag, struct dp *dpi_attr_list); #endif diff -pru dillo2/dpid/main.c g/dpid/main.c --- dillo2/dpid/main.c 2007-10-07 00:36:34.000000000 +0200 +++ g/dpid/main.c 2007-11-24 18:17:14.000000000 +0100 @@ -228,6 +228,7 @@ int main(void) fd_set selected_set; dpi_attr_list = NULL; + services_list = NULL; //daemon(0,0); /* Use 0,1 for feedback */ /* todo: call setsid() ?? */ @@ -258,6 +259,11 @@ int main(void) exit(1); } + /* Init services list */ + services_list = dList_new(8); + /* And get server list */ + fill_services_list(&dpi_attr_list, numdpis, services_list); + /* Remove any sockets that may have been leftover from a crash */ cleanup(sockdir); /* Initialise sockets */ ---------- proto_services.diff ----------------------------------------- diff -pru dillo2/src/capi.c f/src/capi.c --- dillo2/src/capi.c 2007-11-17 15:18:37.000000000 +0100 +++ f/src/capi.c 2007-11-21 04:35:22.000000000 +0100 @@ -240,8 +240,12 @@ static int Capi_dpi_verify_request(Dillo static int Capi_url_uses_dpi(DilloUrl *url, char **server_ptr) { char *p, *server = NULL, *url_str = URL_STR(url); + Dstr *tmp; - if (dStrncasecmp(url_str, "dpi:/", 5) == 0) { + if ((dStrncasecmp(url_str, "http:", 5) == 0) || + (dStrncasecmp(url_str, "about:", 6) == 0)) { + /* Doing nothing returns 0 (url not uses dpi) and server = NULL */ + } else if (dStrncasecmp(url_str, "dpi:/", 5) == 0) { /* dpi prefix, get this server's name */ if ((p = strchr(url_str + 5, '/')) != NULL) { server = dStrndup(url_str + 5, (uint_t)(p - url_str - 5)); @@ -252,16 +256,11 @@ static int Capi_url_uses_dpi(DilloUrl *u dFree(server); server = dStrdup("bookmarks"); } - - } else if (dStrncasecmp(url_str, "ftp:/", 5) == 0) { - server = dStrdup("ftp"); - - } else if (dStrncasecmp(url_str, "https:/", 7) == 0) { - server = dStrdup("https"); - } else if (dStrncasecmp(url_str, "file:", 5) == 0) { - server = dStrdup("file"); - } else if (dStrncasecmp(url_str, "data:", 5) == 0) { - server = dStrdup("datauri"); + } else if ((p = strchr(url_str, ':')) != NULL) { + tmp = dStr_new("proto."); + dStr_append_l(tmp, url_str, p - url_str); + server = tmp->str; + dStr_free(tmp, 0); } return ((*server_ptr = server) ? 1 : 0);