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);