web pages, such XSL/CSS/HTML files.
<!--
- $Id: gfs-virtual.xml,v 1.3 2005-08-05 09:36:15 adam Exp $
+ $Id: gfs-virtual.xml,v 1.4 2006-03-15 13:32:05 adam Exp $
Description of the virtual host mechanism in YAZ GFS
Included in both manual and man page for yaz-ztest
-->
</para>
</listitem>
</varlistentry>
+
+ <varlistentry><term>element <literal>stylesheet</literal> (optional)</term>
+ <listitem>
+ <para>
+ Specifies the stylesheet reference to be part of SRU HTTP responses
+ when the client does not specify one. If neither this is given, nor
+ the client specifies one, no stylesheet reference is part of the
+ SRU HTTP response.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry><term>element <literal>docpath</literal> (optional)</term>
+ <listitem>
+ <para>
+ Specifies a path for local file access using HTTP. All URLs with
+ a leading prefix (/ exluded) that matches the value of docpath
+ are used for file access. For example, if the server is to offer
+ access in directory <literal>xsl</literal>, the docpath would be
+ <literal>xsl</literal> and all URLs of the form
+ <literal>http://host/exl</literal> will result in a local file access.
+ </para>
+ </listitem>
+ </varlistentry>
<varlistentry><term>element <literal>explain</literal> (optional)</term>
<listitem>
-<!-- $Id: yazgfs.xml,v 1.1 2005-12-16 15:01:25 adam Exp $ -->
+<!-- $Id: yazgfs.xml,v 1.2 2006-03-15 13:32:05 adam Exp $ -->
<!-- sample YAZ GFS config file .. see
http://indexdata.dk/yaz/doc/server.vhosts.tkl -->
<yazgfs>
<listen id="public1">tcp:@:9000</listen>
- <server id="server1">
+ <server id="server1" listenref="public1">
<directory>.</directory> <!-- directory where backend is running -->
<config>zebra.cfg</config>
<cql2rpn>pqf.properties</cql2rpn>
+ <docpath>xsl</docpath>
+ <stylesheet>xsl/default.xsl</stylesheet>
<explain xmlns="http://explain.z3950.org/dtd/2.0/">
<serverInfo>
<host>myserver.org</host>
## This file is part of the YAZ toolkit.
## Copyright (C) 1994-2005, Index Data, All rights reserved.
-## $Id: Makefile.am,v 1.28 2006-03-13 11:59:27 adam Exp $
+## $Id: Makefile.am,v 1.29 2006-03-15 13:32:05 adam Exp $
YAZ_VERSION_INFO=2:0:0
cqlstrer.c querytowrbuf.c \
eventl.c seshigh.c statserv.c requestq.c tcpdchk.c \
eventl.h service.c service.h session.h test.c \
- xmlquery.c
+ xmlquery.c \
+ mime.c mime.h
libyaz_la_LDFLAGS=-version-info $(YAZ_VERSION_INFO)
--- /dev/null
+/*
+ * Copyright (C) 1995-2005, Index Data ApS
+ * See the file LICENSE for details.
+ *
+ * $Id: mime.c,v 1.1 2006-03-15 13:32:05 adam Exp $
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <yaz/xmalloc.h>
+
+#include "mime.h"
+
+struct yaz_mime_entry {
+ char *suffix;
+ char *mime_type;
+ struct yaz_mime_entry *next;
+};
+
+struct yaz_mime_info {
+ struct yaz_mime_entry *table;
+};
+
+yaz_mime_types yaz_mime_types_create()
+{
+ yaz_mime_types p = xmalloc(sizeof(*p));
+ p->table = 0;
+ return p;
+}
+
+void yaz_mime_types_add(yaz_mime_types t, const char *suffix,
+ const char *mime_type)
+{
+ struct yaz_mime_entry *e = xmalloc(sizeof(*e));
+ e->mime_type = xstrdup(mime_type);
+ e->suffix = xstrdup(suffix);
+ e->next = t->table;
+ t->table = e;
+}
+
+const char *yaz_mime_lookup_suffix(yaz_mime_types t, const char *suffix)
+{
+ struct yaz_mime_entry *e = t->table;
+ for (; e; e = e->next)
+ {
+ if (!strcmp(e->suffix, suffix))
+ return e->mime_type;
+ }
+ return 0;
+}
+
+const char *yaz_mime_lookup_fname(yaz_mime_types t, const char *fname)
+{
+ const char *cp = strrchr(fname, '.');
+ if (!cp) /* if no . return now */
+ return 0;
+ return yaz_mime_lookup_suffix(t, cp+1); /* skip . */
+}
+
+void yaz_mime_types_destroy(yaz_mime_types t)
+{
+ struct yaz_mime_entry *e = t->table;
+ while (e)
+ {
+ struct yaz_mime_entry *e_next = e->next;
+ xfree(e->suffix);
+ xfree(e->mime_type);
+ xfree(e);
+ e = e_next;
+ }
+ xfree(t);
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
--- /dev/null
+/*
+ * Copyright (C) 1995-2005, Index Data ApS
+ * See the file LICENSE for details.
+ *
+ * $Id: mime.h,v 1.1 2006-03-15 13:32:05 adam Exp $
+ */
+#ifndef MIME_H
+#define MIME_H
+
+typedef struct yaz_mime_info *yaz_mime_types;
+
+yaz_mime_types yaz_mime_types_create();
+void yaz_mime_types_add(yaz_mime_types t, const char *suffix,
+ const char *mime_type);
+const char *yaz_mime_lookup_suffix(yaz_mime_types t, const char *suffix);
+const char *yaz_mime_lookup_fname(yaz_mime_types t, const char *fname);
+void yaz_mime_types_destroy(yaz_mime_types t);
+
+#endif
+
* Copyright (C) 1995-2005, Index Data ApS
* See the file LICENSE for details.
*
- * $Id: seshigh.c,v 1.68 2006-03-13 11:59:27 adam Exp $
+ * $Id: seshigh.c,v 1.69 2006-03-15 13:32:05 adam Exp $
*/
/**
* \file seshigh.c
#include <yaz/comstack.h>
#include "eventl.h"
#include "session.h"
+#include "mime.h"
#include <yaz/proto.h>
#include <yaz/oid.h>
#include <yaz/log.h>
}
}
+/* check if path is OK (1); BAD (0) */
+static int check_path(const char *path)
+{
+ if (*path != '/')
+ return 0;
+ if (strstr(path, ".."))
+ return 0;
+ return 1;
+}
+
+static char *read_file(const char *fname, ODR o, int *sz)
+{
+ char *buf;
+ FILE *inf = fopen(fname, "rb");
+ if (!inf)
+ return 0;
+
+ fseek(inf, 0L, SEEK_END);
+ *sz = ftell(inf);
+ rewind(inf);
+ buf = odr_malloc(o, *sz);
+ fread(buf, 1, *sz, inf);
+ fclose(inf);
+ return buf;
+}
+
static void process_http_request(association *assoc, request *req)
{
Z_HTTP_Request *hreq = req->gdu_request->u.HTTP_Request;
char *charset = 0;
Z_HTTP_Response *hres = 0;
int keepalive = 1;
- char *stylesheet = 0;
+ const char *stylesheet = 0; /* for now .. set later */
Z_SRW_diagnostic *diagnostic = 0;
int num_diagnostic = 0;
const char *host = z_HTTP_header_lookup(hreq->headers, "Host");
p = z_get_HTTP_Response(o, 404);
r = 1;
}
- if (r == 2 && !strcmp(hreq->path, "/test"))
+ if (r == 2 && assoc->docpath && hreq->path[0] == '/'
+ &&
+ /* check if path is a proper prefix of documentroot */
+ strncmp(hreq->path+1, assoc->docpath, strlen(assoc->docpath))
+ == 0)
{
- p = z_get_HTTP_Response(o, 200);
- hres = p->u.HTTP_Response;
- hres->content_buf = "1234567890\n";
- hres->content_len = strlen(hres->content_buf);
+ if (!check_path(hreq->path))
+ {
+ yaz_log(YLOG_LOG, "File %s access forbidden", hreq->path+1);
+ p = z_get_HTTP_Response(o, 404);
+ }
+ else
+ {
+ int content_size = 0;
+ char *content_buf = read_file(hreq->path+1, o, &content_size);
+ if (!content_buf)
+ {
+ yaz_log(YLOG_LOG, "File %s not found", hreq->path+1);
+ p = z_get_HTTP_Response(o, 404);
+ }
+ else
+ {
+ const char *ctype = 0;
+ yaz_mime_types types = yaz_mime_types_create();
+
+ yaz_mime_types_add(types, "xsl", "application/xml");
+ yaz_mime_types_add(types, "xml", "application/xml");
+ yaz_mime_types_add(types, "css", "text/css");
+ yaz_mime_types_add(types, "html", "text/html");
+ yaz_mime_types_add(types, "htm", "text/html");
+ yaz_mime_types_add(types, "txt", "text/plain");
+
+ yaz_mime_types_add(types, "gif", "image/gif");
+ yaz_mime_types_add(types, "png", "image/png");
+ yaz_mime_types_add(types, "jpg", "image/jpeg");
+ yaz_mime_types_add(types, "jpeg", "image/jpeg");
+
+ ctype = yaz_mime_lookup_fname(types, hreq->path);
+ if (!ctype)
+ {
+ yaz_log(YLOG_LOG, "No mime type for %s", hreq->path+1);
+ p = z_get_HTTP_Response(o, 404);
+ }
+ else
+ {
+ p = z_get_HTTP_Response(o, 200);
+ hres = p->u.HTTP_Response;
+ hres->content_buf = content_buf;
+ hres->content_len = content_size;
+ z_HTTP_header_add(o, &hres->headers, "Content-Type", ctype);
+ }
+ yaz_mime_types_destroy(types);
+ }
+ }
r = 1;
}
+
if (r == 2)
{
r = yaz_srw_decode(hreq, &sr, &soap_package, assoc->decode, &charset);
int ret;
p = z_get_HTTP_Response(o, 200);
hres = p->u.HTTP_Response;
+
+ yaz_log(YLOG_LOG, "assoc->stylesheet=%s", assoc->stylesheet);
+ if (!stylesheet)
+ stylesheet = assoc->stylesheet;
+
ret = z_soap_codec_enc_xsl(assoc->encode, &soap_package,
&hres->content_buf, &hres->content_len,
soap_handlers, charset, stylesheet);
assoc->init->implementation_name,
odr_prepend(assoc->encode, "GFS", resp->implementationName));
- version = odr_strdup(assoc->encode, "$Revision: 1.68 $");
+ version = odr_strdup(assoc->encode, "$Revision: 1.69 $");
if (strlen(version) > 10) /* check for unexpanded CVS strings */
version[strlen(version)-2] = '\0';
resp->implementationVersion = odr_prepend(assoc->encode,
* Copyright (C) 1995-2005, Index Data ApS
* See the file LICENSE for details.
*
- * $Id: session.h,v 1.9 2005-06-25 15:46:05 adam Exp $
+ * $Id: session.h,v 1.10 2006-03-15 13:32:05 adam Exp $
*/
/**
* \file session.h
cql_transform_t cql_transform;
void *server_node_ptr;
char *directory;
+ char *docpath;
+ char *stylesheet;
struct gfs_server *next;
};
statserv_options_block *last_control;
cql_transform_t cql_transform;
void *server_node_ptr;
+ const char *docpath;
+ const char *stylesheet;
} association;
association *create_association(IOCHAN channel, COMSTACK link,
* NT threaded server code by
* Chas Woodfield, Fretwell Downing Informatics.
*
- * $Id: statserv.c,v 1.33 2005-10-20 19:28:04 quinn Exp $
+ * $Id: statserv.c,v 1.34 2006-03-15 13:32:05 adam Exp $
*/
/**
n->cql_transform = 0;
n->server_node_ptr = 0;
n->directory = 0;
+ n->docpath = 0;
+ n->stylesheet = 0;
return n;
}
*cp = '\0';
host = vhost;
}
+ assoc->cql_transform = 0;
+ assoc->server_node_ptr = 0;
+ assoc->docpath = 0;
+ assoc->stylesheet = 0;
if (control_block.xml_config[0])
{
struct gfs_server *gfs;
xfree(assoc->init);
assoc->init = 0;
}
+ assoc->docpath = gfs->docpath;
+ assoc->stylesheet = gfs->stylesheet;
assoc->cql_transform = gfs->cql_transform;
assoc->server_node_ptr = gfs->server_node_ptr;
assoc->last_control = &gfs->cb;
}
statserv_setcontrol(0);
assoc->last_control = 0;
- assoc->cql_transform = 0;
- assoc->server_node_ptr = 0;
yaz_log(YLOG_DEBUG, "server select: no match");
return 0;
}
{
statserv_setcontrol(&control_block);
assoc->last_control = &control_block;
- assoc->cql_transform = 0;
- assoc->server_node_ptr = 0;
yaz_log(YLOG_DEBUG, "server select: config=%s", control_block.configname);
return 1;
}
(*gfsp)->directory =
nmem_dup_xml_content(gfs_nmem, ptr->children);
}
+ else if (!strcmp((const char *) ptr->name, "docpath"))
+ {
+ (*gfsp)->docpath =
+ nmem_dup_xml_content(gfs_nmem, ptr->children);
+ }
+ else if (!strcmp((const char *) ptr->name, "stylesheet"))
+ {
+ char *s = nmem_dup_xml_content(gfs_nmem, ptr->children);
+ (*gfsp)->stylesheet =
+ nmem_malloc(gfs_nmem, strlen(s) + 2);
+ sprintf((*gfsp)->stylesheet, "/%s", s);
+ }
+ else if (!strcmp((const char *) ptr->name, "explain"))
+ {
+ ; /* being processed separately */
+ }
+ else
+ {
+ yaz_log(YLOG_FATAL, "Unknown element '%s' in config %s",
+ ptr->name, control_block.xml_config);
+ exit(1);
+ }
}
gfsp = &(*gfsp)->next;
}
# Copyright (C) 1994-2005, Index Data ApS
# All rights reserved.
-# $Id: makefile,v 1.101 2006-03-14 08:50:19 adam Exp $
+# $Id: makefile,v 1.102 2006-03-15 13:32:06 adam Exp $
#
# Programmed by
# Heikki Levanto & Adam Dickmeiss
$(OBJDIR)\zoom-c.obj \
$(OBJDIR)\zoom-opt.obj \
$(OBJDIR)\initopt.obj \
- $(OBJDIR)\xmlquery.obj
+ $(OBJDIR)\xmlquery.obj \
+ $(OBJDIR)\mime.obj
Z3950_OBJS= \
$(OBJDIR)\z-date.obj\