--- 1.8.8 2002/MM/DD
+Added three members in bend_initrequest structure to facilitate
+character set negotiation.
+
+Fixed a bug in frontend server that could cause indefinite
+loops under rare conditions.
+
+Revised character set utilities (charneg.h) so that encoding
+UCS-4, UCSA-4, UTF-16 and UTF-8 are encoded non-privately.
+
+For PQF, directive @term <type> sets term type for Scan/Search.
+Here <type> is general, string, numeric, null. The term type
+is inherited - just like @attr.
+
+New call odr_set_charset that sets character set conversion for
+international-strings on a ODR stream. Prototype is:
+ int odr_set_charset(ODR o, const char *to, const char *from);
+The InternationalString is still represented as C string in YAZ
+so native strings of type UTF-8, ASCII, etc. will work (UTF-16
+won't). On the protocol level, you can use any encoding.
+
+Support for UNIX sockets in ZOOM.
+
Solaris recv sometimes returns errno == ENOENT. It is treated as
EINPROGRESS. COMSTACK patch by Ko van der Sloot.
#!/bin/sh
-# $Id: buildconf.sh,v 1.12 2002-05-13 18:34:53 adam Exp $
-aclocal
+# $Id: buildconf.sh,v 1.13 2002-07-25 12:52:52 adam Exp $
+aclocal
libtoolize --automake --force
automake -a
autoconf
* Copyright (c) 1995-2002, Index Data
* See the file LICENSE for details.
*
- * $Id: client.c,v 1.161 2002-07-12 12:20:34 ja7 Exp $
+ * $Id: client.c,v 1.162 2002-07-25 12:52:53 adam Exp $
*/
#include <stdio.h>
char *charset=NULL, *lang=NULL;
int selected;
- yaz_get_response_charneg(session_mem, p, &charset, &lang, &selected);
+ yaz_get_response_charneg(session_mem, p, &charset, &lang,
+ &selected);
- printf("Accepted character set : `%s'\n", charset);
- printf("Accepted code language : `%s'\n", lang);
+ printf("Accepted character set : %s\n", charset);
+ printf("Accepted code language : %s\n", lang ? lang : "none");
printf("Accepted records in ...: %d\n", selected );
}
}
if (qe->u.term->queryTerm)
{
Z_Term *term = qe->u.term->queryTerm;
- if (term->which == Z_Term_general)
+ switch (term->which)
+ {
+ case Z_Term_general:
printf (" %.*s", term->u.general->len, term->u.general->buf);
+ break;
+ case Z_Term_characterString:
+ printf (" %s", term->u.characterString);
+ break;
+ case Z_Term_numeric:
+ printf (" %d", *term->u.numeric);
+ break;
+ case Z_Term_null:
+ printf (" null");
+ break;
+ }
}
}
-
}
/* see if we can find USR:SearchResult-1 */
int cmd_charset(char* arg)
{
- if (*arg == '\0') {
- printf("Current character set is `%s'\n", (yazCharset)?yazCharset:NULL);
+ char l1[30], l2[30];
+
+ *l1 = *l2 = 0;
+ if (sscanf(arg, "%29s %29s", l1, l2) < 1)
+ {
+ printf("Current character set is `%s'\n", (yazCharset) ?
+ yazCharset:NULL);
return 1;
}
xfree (yazCharset);
yazCharset = NULL;
- if (*arg)
+ if (*l1)
+ yazCharset = xstrdup(l1);
+ if (*l2)
{
- yazCharset = (char *) xmalloc (strlen(arg)+1);
- strcpy (yazCharset, arg);
- }
+ odr_set_charset (out, l1, l2);
+ odr_set_charset (in, l2, l1);
+ }
return 1;
}
/*
- * Copyright (c) 1995-2001, Index Data.
+ * Copyright (c) 1995-2002, Index Data.
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation, in whole or in part, for any purpose, is hereby granted,
* OF THIS SOFTWARE.
*
* $Log: backend.h,v $
- * Revision 1.14 2002-03-20 14:36:00 adam
+ * Revision 1.15 2002-07-25 12:52:53 adam
+ * Character set negotiation updates
+ *
+ * Revision 1.14 2002/03/20 14:36:00 adam
* Additional Search Info for GFS
*
* Revision 1.13 2002/03/05 12:45:49 mike
int (*bend_delete)(void *handle, bend_delete_rr *rr);
int (*bend_scan)(void *handle, bend_scan_rr *rr);
int (*bend_segment)(void *handle, bend_segment_rr *rr);
+
+ ODR decode; /* decoding stream */
+ /* character set and language negotiation - see include/yaz/z-charneg.h */
+ Z_CharSetandLanguageNegotiation *charneg_request;
+ Z_External *charneg_response;
+
} bend_initrequest;
typedef struct bend_initresult
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*
- * $Id: data1.h,v 1.13 2002-07-05 16:04:28 adam Exp $
+ * $Id: data1.h,v 1.14 2002-07-25 12:52:53 adam Exp $
*/
#ifndef DATA1_H
data1_marctab *marc;
data1_sub_elements *sub_elements;
data1_element *main_elements;
+ char *encoding;
} data1_absyn;
/*
const char *tocode,
const char *fromcode);
+YAZ_EXPORT const char *data1_get_encoding (data1_handle dh, data1_node *n);
+
YAZ_END_CDECL
#endif
* Sebastian Hammer, Adam Dickmeiss
*
* $Log: d1_absyn.c,v $
- * Revision 1.31 2002-04-04 20:49:46 adam
+ * Revision 1.32 2002-07-25 12:52:53 adam
+ * Character set negotiation updates
+ *
+ * Revision 1.31 2002/04/04 20:49:46 adam
* New functions yaz_is_abspath, yaz_path_fopen_base
*
* Revision 1.30 2000/12/05 19:07:24 adam
res->name = 0;
res->reference = VAL_NONE;
res->tagset = 0;
+ res->encoding = 0;
tagset_childp = &res->tagset;
res->attset = data1_empty_attset (dh);
}
marcp = &(*marcp)->next;
}
+ else if (!strcmp(cmd, "encoding"))
+ {
+ if (argc != 2)
+ {
+ yaz_log(LOG_WARN, "%s:%d: Bad # or args for encoding",
+ file, lineno);
+ continue;
+ }
+ res->encoding = nmem_strdup (data1_nmem_get(dh), argv[1]);
+ }
else
{
yaz_log(LOG_WARN, "%s:%d: Unknown directive '%s'", file, lineno, cmd);
* Copyright (c) 2002, Index Data.
* See the file LICENSE for details.
*
- * $Id: d1_expat.c,v 1.5 2002-07-11 10:39:49 adam Exp $
+ * $Id: d1_expat.c,v 1.6 2002-07-25 12:52:53 adam Exp $
*/
#if HAVE_EXPAT_H
attr_list[1] = version;
attr_list[2] = "encoding";
- attr_list[3] = encoding;
+ attr_list[3] = "UTF-8"; /* encoding */
attr_list[4] = "standalone";
attr_list[5] = standalone ? "yes" : "no";
* See the file LICENSE for details.
* Sebastian Hammer, Adam Dickmeiss
*
- * $Id: d1_grs.c,v 1.23 2002-07-11 10:40:34 adam Exp $
+ * $Id: d1_grs.c,v 1.24 2002-07-25 12:52:53 adam Exp $
*
*/
res->which = Z_ElementData_elementNotThere;
res->u.elementNotThere = odr_nullval();
}
- else if (n->which == DATA1N_data && (leaf || n->next == NULL))
+ else if (n->which == DATA1N_data && leaf)
{
char str[512];
int toget;
break;
case DATA1I_text:
toget = n->u.data.len;
- if (p && p->u.tag.get_bytes > 0 && p->u.tag.get_bytes < toget)
- toget = p->u.tag.get_bytes;
res->which = Z_ElementData_string;
res->u.string = (char *)odr_malloc(o, toget+1);
memcpy(res->u.string, n->u.data.data, toget);
return res;
}
+static int is_empty_data (data1_node *n)
+{
+ if (n && n->which == DATA1N_data && n->u.data.what == DATA1I_text)
+ {
+ int i = n->u.data.len;
+
+ while (i > 0 && n->u.data.data[i-1] == '\n')
+ i--;
+ if (i == 0)
+ return 1;
+ }
+ return 0;
+}
+
+
static Z_TaggedElement *nodetotaggedelement(data1_handle dh, data1_node *n,
int select, ODR o,
int *len)
if (n->u.tag.element)
tag = n->u.tag.element->tag;
data = n->child;
- leaf = 0;
+
+ /* skip empty data children */
+ while (is_empty_data(data))
+ data = data->next;
+ if (!data)
+ data = n->child;
+ else
+ { /* got one. see if this is the only non-empty one */
+ data1_node *sub = data->next;
+ while (sub && is_empty_data(sub))
+ sub = sub->next;
+ if (!sub)
+ leaf = 1; /* all empty. 'data' is the only child */
+ }
}
/*
* If we're a data element at this point, we need to insert a
}
data = n;
leaf = 1;
+ if (is_empty_data(data))
+ return 0;
}
else
{
* See the file LICENSE for details.
* Sebastian Hammer, Adam Dickmeiss
*
- * $Id: d1_marc.c,v 1.20 2002-07-03 14:09:34 adam Exp $
+ * $Id: d1_marc.c,v 1.21 2002-07-25 12:52:53 adam Exp $
*/
return res;
}
+
/*
* Locate some data under this node. This routine should handle variants
* prettily.
static char *get_data(data1_node *n, int *len)
{
char *r;
+ data1_node *np = 0;
- while (n->which != DATA1N_data && n->child)
- n = n->child;
- if (n->which != DATA1N_data ||
- (n->u.data.what != DATA1I_text && n->u.data.what != DATA1I_num))
+ while (n)
{
- r = "[Structured/included data]";
- *len = strlen(r);
- return r;
+ if (n->which == DATA1N_data)
+ {
+ *len = n->u.data.len;
+ while (*len && d1_isspace(n->u.data.data[*len - 1]))
+ (*len)--;
+ if (*len != 0)
+ return n->u.data.data;
+ }
+ if (n->which == DATA1N_tag)
+ np = n->child;
+ n = n->next;
+ if (!n)
+ {
+ n = np;
+ np = 0;
+ }
}
-
- *len = n->u.data.len;
- while (*len && d1_isspace(n->u.data.data[*len - 1]))
- (*len)--;
- return n->u.data.data;
+ r = "";
+ *len = strlen(r);
+ return r;
}
static void memint (char *p, int val, int len)
* See the file LICENSE for details.
* Sebastian Hammer, Adam Dickmeiss
*
- * $Id: d1_read.c,v 1.45 2002-07-05 16:04:28 adam Exp $
+ * $Id: d1_read.c,v 1.46 2002-07-25 12:52:53 adam Exp $
*/
#include <assert.h>
}
static void data1_iconv_s (data1_handle dh, NMEM m, data1_node *n,
- iconv_t t, WRBUF wrbuf)
+ iconv_t t, WRBUF wrbuf, const char *tocode)
{
for (; n; n = n->next)
{
}
}
break;
+ case DATA1N_preprocess:
+ if (strcmp(n->u.preprocess.target, "xml") == 0)
+ {
+ data1_xattr *p = n->u.preprocess.attributes;
+ for (; p; p = p->next)
+ if (strcmp (p->name, "encoding") == 0)
+ p->value = nmem_strdup (m, tocode);
+ }
+ break;
}
- data1_iconv_s (dh, m, n->child, t, wrbuf);
+ data1_iconv_s (dh, m, n->child, t, wrbuf, tocode);
}
}
#endif
+const char *data1_get_encoding (data1_handle dh, data1_node *n)
+{
+ /* see if we have an xml header that specifies encoding */
+ if (n && n->child && n->child->which == DATA1N_preprocess &&
+ strcmp (n->child->u.preprocess.target, "xml") == 0)
+ {
+ data1_xattr *xp = n->child->u.preprocess.attributes;
+ for (; xp; xp = xp->next)
+ if (!strcmp (xp->name, "encoding") == 0)
+ return xp->value;
+ }
+ /* no encoding in header, so see if "encoding" was specified for abs */
+ if (n && n->which == DATA1N_root &&
+ n->u.root.absyn && n->u.root.absyn->encoding)
+ return n->u.root.absyn->encoding;
+ /* none of above, return a hard coded default */
+ return "ISO-8859-1";
+}
+
int data1_iconv (data1_handle dh, NMEM m, data1_node *n,
const char *tocode,
const char *fromcode)
{
#if HAVE_ICONV_H
- WRBUF wrbuf = wrbuf_alloc();
- iconv_t t = iconv_open (tocode, fromcode);
- if (t == (iconv_t) (-1))
- return -1;
- data1_iconv_s (dh, m, n, t, wrbuf);
- iconv_close (t);
- wrbuf_free (wrbuf, 1);
+ if (strcmp (tocode, fromcode))
+ {
+ WRBUF wrbuf = wrbuf_alloc();
+ iconv_t t = iconv_open (tocode, fromcode);
+ if (t == (iconv_t) (-1))
+ return -1;
+ data1_iconv_s (dh, m, n, t, wrbuf, tocode);
+ iconv_close (t);
+ wrbuf_free (wrbuf, 1);
+ }
return 0;
#else
return -2;
* See the file LICENSE for details.
* Sebastian Hammer, Adam Dickmeiss
*
- * $Id: d1_write.c,v 1.14 2002-07-05 12:42:52 adam Exp $
+ * $Id: d1_write.c,v 1.15 2002-07-25 12:52:53 adam Exp $
*/
#include <string.h>
return l;
}
-static int nodetoidsgml(data1_node *n, int select, WRBUF b, int col)
+static void indent (WRBUF b, int col)
+{
+ int i;
+ for (i = 0; i<col; i++)
+ wrbuf_putc (b, ' ');
+}
+
+static void wrbuf_write_cdata(WRBUF b, const char *msg, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ {
+ switch (msg[i])
+ {
+ case '"':
+ wrbuf_puts (b, """);
+ break;
+ case '>':
+ wrbuf_puts (b, ">");
+ break;
+ case '<':
+ wrbuf_puts (b, "<");
+ break;
+#if 0
+ case '&':
+ wrbuf_puts (b, "&");
+ break;
+#endif
+ default:
+ wrbuf_putc(b, msg[i]);
+ }
+ }
+}
+
+static void wrbuf_put_cdata(WRBUF b, const char *msg)
+{
+ wrbuf_write_cdata (b, msg, strlen(msg));
+}
+
+static int nodetoidsgml(data1_node *n, int select, WRBUF b, int col,
+ int pretty_format)
{
data1_node *c;
- char line[1024];
for (c = n->child; c; c = c->next)
{
if (c->which == DATA1N_preprocess)
{
data1_xattr *p;
-
-#if PRETTY_FORMAT
- sprintf (line, "%*s", col, "");
- wrbuf_puts (b, line);
-#endif
+
+ if (pretty_format)
+ indent (b, col);
wrbuf_puts (b, "<?");
- wrbuf_puts (b, c->u.preprocess.target);
+ wrbuf_put_cdata (b, c->u.preprocess.target);
for (p = c->u.preprocess.attributes; p; p = p->next)
{
wrbuf_putc (b, ' ');
- wrbuf_puts (b, p->name);
+ wrbuf_put_cdata (b, p->name);
wrbuf_putc (b, '=');
wrbuf_putc (b, '"');
- wrbuf_puts (b, p->value);
+ wrbuf_put_cdata (b, p->value);
wrbuf_putc (b, '"');
}
if (c->child)
wrbuf_puts(b, " ");
- if (nodetoidsgml(c, select, b, (col > 40) ? 40 : col+2) < 0)
+ if (nodetoidsgml(c, select, b, (col > 40) ? 40 : col+2,
+ pretty_format) < 0)
return -1;
wrbuf_puts (b, "?>\n");
}
tag = c->u.tag.tag;
if (!data1_matchstr(tag, "wellknown")) /* skip wellknown */
{
- if (nodetoidsgml(c, select, b, col) < 0)
+ if (nodetoidsgml(c, select, b, col, pretty_format) < 0)
return -1;
}
else
{
data1_xattr *p;
-#if PRETTY_FORMAT
- sprintf (line, "%*s", col, "");
- wrbuf_puts (b, line);
-#endif
+ if (pretty_format)
+ indent (b, col);
wrbuf_puts (b, "<");
- wrbuf_puts (b, tag);
+ wrbuf_put_cdata (b, tag);
for (p = c->u.tag.attributes; p; p = p->next)
{
wrbuf_putc (b, ' ');
- wrbuf_puts (b, p->name);
+ wrbuf_put_cdata (b, p->name);
wrbuf_putc (b, '=');
wrbuf_putc (b, '"');
- wrbuf_puts (b, p->value);
+ wrbuf_put_cdata (b, p->value);
wrbuf_putc (b, '"');
}
wrbuf_puts(b, ">");
-#if PRETTY_FORMAT
- wrbuf_puts(b, "\n");
-#endif
- if (nodetoidsgml(c, select, b, (col > 40) ? 40 : col+2) < 0)
+ if (pretty_format)
+ wrbuf_puts(b, "\n");
+ if (nodetoidsgml(c, select, b, (col > 40) ? 40 : col+2,
+ pretty_format) < 0)
return -1;
-#if PRETTY_FORMAT
- sprintf (line, "%*s", col);
- wrbuf_puts(b, line);
-#endif
+ if (pretty_format)
+ indent (b, col);
wrbuf_puts(b, "</");
- wrbuf_puts(b, tag);
+ wrbuf_put_cdata(b, tag);
wrbuf_puts(b, ">");
-#if PRETTY_FORMAT
- wrbuf_puts (b, "\n");
-#endif
+ if (pretty_format)
+ wrbuf_puts (b, "\n");
}
}
else if (c->which == DATA1N_data || c->which == DATA1N_comment)
int first = 1;
int lcol = col;
-#if PRETTY_FORMAT
- if (!c->u.data.formatted_text)
- {
- sprintf(line, "%*s", col, "");
- wrbuf_write(b, line, strlen(line));
- }
-#endif
+ if (pretty_format && !c->u.data.formatted_text)
+ indent (b, col);
if (c->which == DATA1N_comment)
- {
- wrbuf_write (b, "<!--", 4);
- }
+ wrbuf_puts (b, "<!--");
switch (c->u.data.what)
{
case DATA1I_text:
-#if PRETTY_FORMAT
- if (c->u.data.formatted_text)
+ if (!pretty_format || c->u.data.formatted_text)
{
- wrbuf_write (b, p, l);
+ wrbuf_write_cdata (b, p, l);
}
else
{
if (lcol + (wlen = wordlen(p, l)) > IDSGML_MARGIN &&
wlen < IDSGML_MARGIN)
{
- sprintf(line, "\n%*s", col, "");
+ wrbuf_puts (b, "\n");
+ indent (b, col);
lcol = col;
- wrbuf_write(b, line, strlen(line));
first = 1;
}
if (!first)
}
first = 0;
}
- wrbuf_write(b, "\n", 1);
+ wrbuf_puts(b, "\n");
}
-#else
- wrbuf_write (b, p, l);
-#endif
break;
case DATA1I_num:
- wrbuf_write(b, c->u.data.data, c->u.data.len);
-#if PRETTY_FORMAT
- wrbuf_puts(b, "\n");
-#endif
+ wrbuf_write_cdata(b, c->u.data.data, c->u.data.len);
+ if (pretty_format)
+ wrbuf_puts(b, "\n");
break;
case DATA1I_oid:
- wrbuf_write(b, c->u.data.data, c->u.data.len);
-#if PRETTY_FORMAT
- wrbuf_puts(b, "\n");
-#endif
+ wrbuf_write_cdata(b, c->u.data.data, c->u.data.len);
+ if (pretty_format)
+ wrbuf_puts(b, "\n");
}
if (c->which == DATA1N_comment)
{
wrbuf_puts(b, "-->");
-#if PRETTY_FORMAT
- wrbuf_puts(b, "\n");
-#endif
+ if (pretty_format)
+ wrbuf_puts(b, "\n");
}
}
}
wrbuf_rewind(b);
- if (nodetoidsgml(n, select, b, 0))
+ if (nodetoidsgml(n, select, b, 0, 0 /* no pretty format */))
return 0;
*len = wrbuf_len(b);
return wrbuf_buf(b);
* Copyright (c) 1995-2002, Index Data
* See the file LICENSE for details.
*
- * $Id: seshigh.c,v 1.130 2002-06-18 21:30:39 adam Exp $
+ * $Id: seshigh.c,v 1.131 2002-07-25 12:52:54 adam Exp $
*/
/*
#include <yaz/logrpn.h>
#include <yaz/statserv.h>
#include <yaz/diagbib1.h>
+#include <yaz/charneg.h>
+#include <yaz/otherinfo.h>
#include <yaz/backend.h>
iochan_clearflag(h, EVENT_OUTPUT|EVENT_INPUT);
iochan_setflag(h, assoc->cs_get_mask);
}
+ else
+ assoc->cs_put_mask = EVENT_OUTPUT;
break;
default:
if (conn->io_pending & CS_WANT_WRITE)
Z_APDU *apdu = zget_APDU(assoc->encode, Z_APDU_initResponse);
Z_InitResponse *resp = apdu->u.initResponse;
bend_initresult *binitres;
- char options[100];
+
+ char options[140];
xfree (assoc->init);
assoc->init = (bend_initrequest *) xmalloc (sizeof(*assoc->init));
assoc->init->bend_scan = NULL;
assoc->init->bend_segment = NULL;
assoc->init->bend_fetch = NULL;
+ assoc->init->charneg_request = NULL;
+ assoc->init->charneg_response = NULL;
+ assoc->init->decode = assoc->decode;
+
+ if (ODR_MASK_GET(req->options, Z_Options_negotiationModel))
+ {
+ Z_CharSetandLanguageNegotiation *negotiation =
+ yaz_get_charneg_record (req->otherInfo);
+ if (negotiation->which == Z_CharSetandLanguageNegotiation_proposal)
+ assoc->init->charneg_request = negotiation;
+ }
assoc->init->peer_name =
odr_strdup (assoc->encode, cs_addrstr(assoc->client_link));
if (ODR_MASK_GET(req->options, Z_Options_concurrentOperations))
{
ODR_MASK_SET(resp->options, Z_Options_concurrentOperations);
- strcat(options, " concurop");
+ strcat(options, " concurrop");
}
if (ODR_MASK_GET(req->options, Z_Options_sort) && assoc->init->bend_sort)
{
ODR_MASK_SET(resp->options, Z_Options_sort);
strcat(options, " sort");
}
+
+ if (ODR_MASK_GET(req->options, Z_Options_negotiationModel)
+ && assoc->init->charneg_response)
+ {
+ Z_OtherInformation **p;
+ Z_OtherInformationUnit *p0;
+
+ yaz_oi_APDU(apdu, &p);
+
+ if ((p0=yaz_oi_update(p, assoc->encode, NULL, 0, 0))) {
+ ODR_MASK_SET(resp->options, Z_Options_negotiationModel);
+
+ p0->which = Z_OtherInfo_externallyDefinedInfo;
+ p0->information.externallyDefinedInfo =
+ assoc->init->charneg_response;
+ }
+ ODR_MASK_SET(resp->options, Z_Options_negotiationModel);
+ strcat(options, " negotiation");
+ }
+
if (ODR_MASK_GET(req->protocolVersion, Z_ProtocolVersion_1))
{
ODR_MASK_SET(resp->protocolVersion, Z_ProtocolVersion_1);
ODR_MASK_SET(resp->protocolVersion, Z_ProtocolVersion_3);
assoc->version = 3;
}
+
yaz_log(LOG_LOG, "Negotiated to v%d: %s", assoc->version, options);
assoc->maximumRecordSize = *req->maximumRecordSize;
if (assoc->maximumRecordSize > control_block->maxrecordsize)
-; $Id: yaz.nsi,v 1.8 2002-06-05 21:10:16 adam Exp $
+; $Id: yaz.nsi,v 1.9 2002-07-25 12:52:54 adam Exp $
!define VERSION "1.8.8"
File ..\util\*.tcl
SetOutPath $INSTDIR\odr
File ..\odr\*.c
+ File ..\odr\*.h
SetOutPath $INSTDIR\z39.50
File ..\z39.50\*.c
File ..\z39.50\*.asn