|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* $LynxId: HTVMS_WaisUI.c,v 1.19 2013/05/03 20:51:49 tom Exp $
|
|
Packit |
f574b8 |
* HTVMS_WAISUI.c
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* Adaptation for Lynx by F.Macrides (macrides@sci.wfeb.edu)
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* 30-May-1994 FM Initial version.
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Routines originally from UI.c -- FM
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
/* WIDE AREA INFORMATION SERVER SOFTWARE:
|
|
Packit |
f574b8 |
* No guarantees or restrictions. See the readme file for the full standard
|
|
Packit |
f574b8 |
* disclaimer.
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* Brewster@think.com
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* this is a simple ui toolkit for building other ui's on top.
|
|
Packit |
f574b8 |
* -brewster
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* top level functions:
|
|
Packit |
f574b8 |
* generate_search_apdu
|
|
Packit |
f574b8 |
* generate_retrieval_apdu
|
|
Packit |
f574b8 |
* interpret_message
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* to do:
|
|
Packit |
f574b8 |
* generate multiple queries for long documents.
|
|
Packit |
f574b8 |
* this will crash if the file being retrieved is larger than 100k.
|
|
Packit |
f574b8 |
* do log_write()
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#include <HTUtils.h>
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#ifdef VMS
|
|
Packit |
f574b8 |
#include <HTVMS_WaisUI.h>
|
|
Packit |
f574b8 |
#include <HTVMS_WaisProt.h>
|
|
Packit |
f574b8 |
#include <HTTCP.h>
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#undef MAXINT /* we don't need it here, and www_tcp.h may conflict */
|
|
Packit |
f574b8 |
#include <math.h>
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#include <LYexit.h>
|
|
Packit |
f574b8 |
#include <LYLeaks.h>
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
void log_write(char *s GCC_UNUSED)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
return;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* returns a pointer in the buffer of the first free byte.
|
|
Packit |
f574b8 |
if it overflows, then NULL is returned
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
char *generate_search_apdu(char *buff, /* buffer to hold the apdu */
|
|
Packit |
f574b8 |
long *buff_len, /* length of the buffer changed to reflect new data written */
|
|
Packit |
f574b8 |
char *seed_words, /* string of the seed words */
|
|
Packit |
f574b8 |
char *database_name,
|
|
Packit |
f574b8 |
DocObj **docobjs,
|
|
Packit |
f574b8 |
long maxDocsRetrieved)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
/* local variables */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
SearchAPDU *search3;
|
|
Packit |
f574b8 |
char *end_ptr;
|
|
Packit |
f574b8 |
static char *database_names[2] =
|
|
Packit |
f574b8 |
{"", 0};
|
|
Packit |
f574b8 |
any refID;
|
|
Packit |
f574b8 |
WAISSearch *query;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
refID.size = 1;
|
|
Packit |
f574b8 |
refID.bytes = "3";
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
database_names[0] = database_name;
|
|
Packit |
f574b8 |
query = makeWAISSearch(seed_words,
|
|
Packit |
f574b8 |
docobjs, /* DocObjsPtr */
|
|
Packit |
f574b8 |
0,
|
|
Packit |
f574b8 |
1, /* DateFactor */
|
|
Packit |
f574b8 |
0, /* BeginDateRange */
|
|
Packit |
f574b8 |
0, /* EndDateRange */
|
|
Packit |
f574b8 |
maxDocsRetrieved
|
|
Packit |
f574b8 |
);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
search3 = makeSearchAPDU(30,
|
|
Packit |
f574b8 |
5000, /* should be large */
|
|
Packit |
f574b8 |
30,
|
|
Packit |
f574b8 |
1, /* replace indicator */
|
|
Packit |
f574b8 |
"", /* result set name */
|
|
Packit |
f574b8 |
database_names, /* database name */
|
|
Packit |
f574b8 |
QT_RelevanceFeedbackQuery, /* query_type */
|
|
Packit |
f574b8 |
0, /* element name */
|
|
Packit |
f574b8 |
NULL, /* reference ID */
|
|
Packit |
f574b8 |
query);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
end_ptr = writeSearchAPDU(search3, buff, buff_len);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
CSTFreeWAISSearch(query);
|
|
Packit |
f574b8 |
freeSearchAPDU(search3);
|
|
Packit |
f574b8 |
return (end_ptr);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* returns a pointer into the buffer of the next free byte.
|
|
Packit |
f574b8 |
if it overflowed, then NULL is returned
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *generate_retrieval_apdu(char *buff,
|
|
Packit |
f574b8 |
long *buff_len, /* length of the buffer changed to reflect new data written */
|
|
Packit |
f574b8 |
any *docID,
|
|
Packit |
f574b8 |
long chunk_type,
|
|
Packit |
f574b8 |
long start,
|
|
Packit |
f574b8 |
long end,
|
|
Packit |
f574b8 |
char *type,
|
|
Packit |
f574b8 |
char *database_name)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
SearchAPDU *search;
|
|
Packit |
f574b8 |
char *end_ptr;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
static char *database_names[2];
|
|
Packit |
f574b8 |
static char *element_names[3];
|
|
Packit |
f574b8 |
any refID;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
DocObj *DocObjs[2];
|
|
Packit |
f574b8 |
any *query; /* changed from char* by brewster */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (NULL == type)
|
|
Packit |
f574b8 |
type = s_strdup("TEXT");
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
database_names[0] = database_name;
|
|
Packit |
f574b8 |
database_names[1] = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
element_names[0] = " ";
|
|
Packit |
f574b8 |
element_names[1] = ES_DocumentText;
|
|
Packit |
f574b8 |
element_names[2] = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
refID.size = 1;
|
|
Packit |
f574b8 |
refID.bytes = "3";
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
switch (chunk_type) {
|
|
Packit |
f574b8 |
case CT_line:
|
|
Packit |
f574b8 |
DocObjs[0] = makeDocObjUsingLines(docID, type, start, end);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case CT_byte:
|
|
Packit |
f574b8 |
DocObjs[0] = makeDocObjUsingBytes(docID, type, start, end);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
DocObjs[1] = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
query = makeWAISTextQuery(DocObjs);
|
|
Packit |
f574b8 |
search = makeSearchAPDU(10, 16, 15,
|
|
Packit |
f574b8 |
1, /* replace indicator */
|
|
Packit |
f574b8 |
"FOO", /* result set name */
|
|
Packit |
f574b8 |
database_names, /* database name */
|
|
Packit |
f574b8 |
QT_TextRetrievalQuery, /* query_type */
|
|
Packit |
f574b8 |
element_names, /* element name */
|
|
Packit |
f574b8 |
&refID, /* reference ID */
|
|
Packit |
f574b8 |
query);
|
|
Packit |
f574b8 |
end_ptr = writeSearchAPDU(search, buff, buff_len);
|
|
Packit |
f574b8 |
CSTFreeWAISTextQuery(query);
|
|
Packit |
f574b8 |
freeSearchAPDU(search);
|
|
Packit |
f574b8 |
return (end_ptr);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* this is a safe version of unix 'read' it does all the checking
|
|
Packit |
f574b8 |
* and looping necessary
|
|
Packit |
f574b8 |
* to those trying to modify the transport code to use non-UNIX streams:
|
|
Packit |
f574b8 |
* This is the function to modify!
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
static long read_from_stream(int d, char *buf, long nbytes)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
long didRead;
|
|
Packit |
f574b8 |
long toRead = nbytes;
|
|
Packit |
f574b8 |
long totalRead = 0; /* paranoia */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
while (toRead > 0) {
|
|
Packit |
f574b8 |
didRead = NETREAD(d, buf, (int) toRead);
|
|
Packit |
f574b8 |
if (didRead == HT_INTERRUPTED)
|
|
Packit |
f574b8 |
return (HT_INTERRUPTED);
|
|
Packit |
f574b8 |
if (didRead == -1) /* error */
|
|
Packit |
f574b8 |
return (-1);
|
|
Packit |
f574b8 |
if (didRead == 0) /* eof */
|
|
Packit |
f574b8 |
return (-2); /* maybe this should return 0? */
|
|
Packit |
f574b8 |
toRead -= didRead;
|
|
Packit |
f574b8 |
buf += didRead;
|
|
Packit |
f574b8 |
totalRead += didRead;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
if (totalRead != nbytes) /* we overread for some reason */
|
|
Packit |
f574b8 |
return (-totalRead); /* bad news */
|
|
Packit |
f574b8 |
return (totalRead);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* returns the length of the response, 0 if an error */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
static long transport_message(long connection,
|
|
Packit |
f574b8 |
char *request_message,
|
|
Packit |
f574b8 |
long request_length,
|
|
Packit |
f574b8 |
char *response_message,
|
|
Packit |
f574b8 |
long response_buffer_length)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
WAISMessage header;
|
|
Packit |
f574b8 |
long response_length;
|
|
Packit |
f574b8 |
int rv;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* Write out message. Read back header. Figure out response length. */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (request_length + HEADER_LENGTH !=
|
|
Packit |
f574b8 |
NETWRITE(connection, request_message,
|
|
Packit |
f574b8 |
(int) (request_length + HEADER_LENGTH)))
|
|
Packit |
f574b8 |
return 0;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* read for the first '0' */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
while (1) {
|
|
Packit |
f574b8 |
rv = read_from_stream(connection, response_message, 1);
|
|
Packit |
f574b8 |
if (rv == HT_INTERRUPTED)
|
|
Packit |
f574b8 |
return HT_INTERRUPTED;
|
|
Packit |
f574b8 |
if (rv < 0)
|
|
Packit |
f574b8 |
return 0;
|
|
Packit |
f574b8 |
if ('0' == response_message[0])
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
rv = read_from_stream(connection, response_message + 1, HEADER_LENGTH - 1);
|
|
Packit |
f574b8 |
if (rv == HT_INTERRUPTED)
|
|
Packit |
f574b8 |
return HT_INTERRUPTED;
|
|
Packit |
f574b8 |
if (rv < 0)
|
|
Packit |
f574b8 |
return 0;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
readWAISPacketHeader(response_message, &header);
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char length_array[11];
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
LYStrNCpy(length_array, header.msg_len, 10);
|
|
Packit |
f574b8 |
response_length = atol(length_array);
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
if(verbose){
|
|
Packit |
f574b8 |
printf("WAIS header: '%s' length_array: '%s'\n",
|
|
Packit |
f574b8 |
response_message, length_array);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
if (response_length > response_buffer_length) {
|
|
Packit |
f574b8 |
/* we got a message that is too long, therefore empty the message out,
|
|
Packit |
f574b8 |
and return 0 */
|
|
Packit |
f574b8 |
long i;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
for (i = 0; i < response_length; i++) {
|
|
Packit |
f574b8 |
rv = read_from_stream(connection,
|
|
Packit |
f574b8 |
response_message + HEADER_LENGTH,
|
|
Packit |
f574b8 |
1);
|
|
Packit |
f574b8 |
if (rv == HT_INTERRUPTED)
|
|
Packit |
f574b8 |
return HT_INTERRUPTED;
|
|
Packit |
f574b8 |
if (rv < 0)
|
|
Packit |
f574b8 |
return 0;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
return (0);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
rv = read_from_stream(connection,
|
|
Packit |
f574b8 |
response_message + HEADER_LENGTH,
|
|
Packit |
f574b8 |
response_length);
|
|
Packit |
f574b8 |
if (rv == HT_INTERRUPTED)
|
|
Packit |
f574b8 |
return HT_INTERRUPTED;
|
|
Packit |
f574b8 |
if (rv < 0)
|
|
Packit |
f574b8 |
return 0;
|
|
Packit |
f574b8 |
return (response_length);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* returns the number of bytes written. 0 if an error */
|
|
Packit |
f574b8 |
long interpret_message(char *request_message,
|
|
Packit |
f574b8 |
long request_length, /* length of the buffer */
|
|
Packit |
f574b8 |
char *response_message,
|
|
Packit |
f574b8 |
long response_buffer_length,
|
|
Packit |
f574b8 |
long connection,
|
|
Packit |
f574b8 |
boolean verbose GCC_UNUSED)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
long response_length;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* ?
|
|
Packit |
f574b8 |
if(verbose){
|
|
Packit |
f574b8 |
printf ("sending");
|
|
Packit |
f574b8 |
if(hostname_internal && strlen(hostname_internal) > 0)
|
|
Packit |
f574b8 |
printf(" to host %s", hostname_internal);
|
|
Packit |
f574b8 |
if(service_name && strlen(service_name) > 0)
|
|
Packit |
f574b8 |
printf(" for service %s", service_name);
|
|
Packit |
f574b8 |
printf("\n");
|
|
Packit |
f574b8 |
twais_dsply_rsp_apdu(request_message + HEADER_LENGTH,
|
|
Packit |
f574b8 |
request_length);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
writeWAISPacketHeader(request_message,
|
|
Packit |
f574b8 |
request_length,
|
|
Packit |
f574b8 |
(long) 'z', /* Z39.50 */
|
|
Packit |
f574b8 |
"wais ", /* server name */
|
|
Packit |
f574b8 |
(long) NO_COMPRESSION, /* no compression */
|
|
Packit |
f574b8 |
(long) NO_ENCODING, (long) HEADER_VERSION);
|
|
Packit |
f574b8 |
if (connection != 0) {
|
|
Packit |
f574b8 |
response_length = transport_message(connection, request_message,
|
|
Packit |
f574b8 |
request_length,
|
|
Packit |
f574b8 |
response_message,
|
|
Packit |
f574b8 |
response_buffer_length);
|
|
Packit |
f574b8 |
if (response_length == HT_INTERRUPTED)
|
|
Packit |
f574b8 |
return (HT_INTERRUPTED);
|
|
Packit |
f574b8 |
} else
|
|
Packit |
f574b8 |
return (0);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (response_length);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* modifies the string to exclude all seeker codes. sets length to
|
|
Packit |
f574b8 |
the new length. */
|
|
Packit |
f574b8 |
static char *delete_seeker_codes(char *string, long *length)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
long original_count; /* index into the original string */
|
|
Packit |
f574b8 |
long new_count = 0; /* index into the collapsed string */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
for (original_count = 0; original_count < *length; original_count++) {
|
|
Packit |
f574b8 |
if (27 == string[original_count]) {
|
|
Packit |
f574b8 |
/* then we have an escape code */
|
|
Packit |
f574b8 |
/* if the next letter is '(' or ')', then ignore two letters */
|
|
Packit |
f574b8 |
if ('(' == string[original_count + 1] ||
|
|
Packit |
f574b8 |
')' == string[original_count + 1])
|
|
Packit |
f574b8 |
original_count += 1; /* it is a term marker */
|
|
Packit |
f574b8 |
else
|
|
Packit |
f574b8 |
original_count += 4; /* it is a paragraph marker */
|
|
Packit |
f574b8 |
} else
|
|
Packit |
f574b8 |
string[new_count++] = string[original_count];
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
*length = new_count;
|
|
Packit |
f574b8 |
return (string);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#if defined(VMS) && defined(__GNUC__) /* 10-AUG-1995 [pr] */
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
Workaround for an obscure bug in gcc's 2.6.[123] and 2.7.0 vax/vms port;
|
|
Packit |
f574b8 |
sometimes global variables will end up not being defined properly,
|
|
Packit |
f574b8 |
causing first gas to assume they're routines, then the linker to complain
|
|
Packit |
f574b8 |
about unresolved symbols, and finally the program to reference the wrong
|
|
Packit |
f574b8 |
objects (provoking ACCVIO). It's triggered by the specific ordering of
|
|
Packit |
f574b8 |
variable usage in the source code, hence rarely appears. This bug is
|
|
Packit |
f574b8 |
fixed in gcc 2.7.1, and was not present in 2.6.0 and earlier.
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
Make a reference to VAXCRTL's _ctype_[], and also one to this dummy
|
|
Packit |
f574b8 |
variable itself to prevent any "defined but not used" warning.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
static __const void *__const ctype_dummy[] =
|
|
Packit |
f574b8 |
{&_ctype_, &ctype_dummy};
|
|
Packit |
f574b8 |
#endif /* VMS && __GNUC__ */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* returns a pointer to a string with good stuff */
|
|
Packit |
f574b8 |
char *trim_junk(char *headline)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
long length = strlen(headline) + 1; /* include the trailing null */
|
|
Packit |
f574b8 |
size_t i;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
headline = delete_seeker_codes(headline, &length);
|
|
Packit |
f574b8 |
/* delete leading spaces */
|
|
Packit |
f574b8 |
for (i = 0; i < strlen(headline); i++) {
|
|
Packit |
f574b8 |
if (isprint(headline[i])) {
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
headline = headline + i;
|
|
Packit |
f574b8 |
/* delete trailing stuff */
|
|
Packit |
f574b8 |
for (i = strlen(headline) - 1; i > 0; i--) {
|
|
Packit |
f574b8 |
if (isprint(headline[i])) {
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
headline[i] = '\0';
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
return (headline);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Routines originally from ZProt.c -- FM
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
/* WIDE AREA INFORMATION SERVER SOFTWARE:`
|
|
Packit |
f574b8 |
* No guarantees or restrictions. See the readme file for the full standard
|
|
Packit |
f574b8 |
* disclaimer.
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* 3.26.90 Harry Morris, morris@think.com
|
|
Packit |
f574b8 |
* 3.30.90 Harry Morris - Changed any->bits to any->bytes
|
|
Packit |
f574b8 |
* 4.11.90 HWM - generalized conditional includes (see c-dialect.h)
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#define RESERVE_SPACE_FOR_HEADER(spaceLeft) \
|
|
Packit |
f574b8 |
*spaceLeft -= HEADER_LEN;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#define RELEASE_HEADER_SPACE(spaceLeft) \
|
|
Packit |
f574b8 |
if (*spaceLeft > 0) \
|
|
Packit |
f574b8 |
*spaceLeft += HEADER_LEN;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
InitResponseAPDU *makeInitResponseAPDU(boolean result,
|
|
Packit |
f574b8 |
boolean search,
|
|
Packit |
f574b8 |
boolean present,
|
|
Packit |
f574b8 |
boolean deleteIt,
|
|
Packit |
f574b8 |
boolean accessControl,
|
|
Packit |
f574b8 |
boolean resourceControl,
|
|
Packit |
f574b8 |
long prefSize,
|
|
Packit |
f574b8 |
long maxMsgSize,
|
|
Packit |
f574b8 |
char *auth,
|
|
Packit |
f574b8 |
char *id,
|
|
Packit |
f574b8 |
char *name,
|
|
Packit |
f574b8 |
char *version,
|
|
Packit |
f574b8 |
any *refID,
|
|
Packit |
f574b8 |
void *userInfo)
|
|
Packit |
f574b8 |
/* build an initResponse APDU with user specified information */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
InitResponseAPDU *init = (InitResponseAPDU *) s_malloc((size_t) sizeof(InitResponseAPDU));
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
init->PDUType = initResponseAPDU;
|
|
Packit |
f574b8 |
init->Result = result;
|
|
Packit |
f574b8 |
init->willSearch = search;
|
|
Packit |
f574b8 |
init->willPresent = present;
|
|
Packit |
f574b8 |
init->willDelete = deleteIt;
|
|
Packit |
f574b8 |
init->supportAccessControl = accessControl;
|
|
Packit |
f574b8 |
init->supportResourceControl = resourceControl;
|
|
Packit |
f574b8 |
init->PreferredMessageSize = prefSize;
|
|
Packit |
f574b8 |
init->MaximumRecordSize = maxMsgSize;
|
|
Packit |
f574b8 |
init->IDAuthentication = s_strdup(auth);
|
|
Packit |
f574b8 |
init->ImplementationID = s_strdup(id);
|
|
Packit |
f574b8 |
init->ImplementationName = s_strdup(name);
|
|
Packit |
f574b8 |
init->ImplementationVersion = s_strdup(version);
|
|
Packit |
f574b8 |
init->ReferenceID = duplicateAny(refID);
|
|
Packit |
f574b8 |
init->UserInformationField = userInfo; /* not copied! */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (init);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
void freeInitResponseAPDU(InitResponseAPDU *init)
|
|
Packit |
f574b8 |
/* free an initAPDU */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
s_free(init->IDAuthentication);
|
|
Packit |
f574b8 |
s_free(init->ImplementationID);
|
|
Packit |
f574b8 |
s_free(init->ImplementationName);
|
|
Packit |
f574b8 |
s_free(init->ImplementationVersion);
|
|
Packit |
f574b8 |
freeAny(init->ReferenceID);
|
|
Packit |
f574b8 |
s_free(init);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *writeInitResponseAPDU(InitResponseAPDU *init, char *buffer, long *len)
|
|
Packit |
f574b8 |
/* write the initResponse to a buffer, adding system information */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char *buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
|
|
Packit |
f574b8 |
long size;
|
|
Packit |
f574b8 |
bit_map *optionsBM = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
RESERVE_SPACE_FOR_HEADER(len);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
buf = writePDUType(init->PDUType, buf, len);
|
|
Packit |
f574b8 |
buf = writeBoolean(init->Result, buf, len);
|
|
Packit |
f574b8 |
buf = writeProtocolVersion(buf, len);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
optionsBM = makeBitMap((unsigned long) 5, init->willSearch, init->willPresent,
|
|
Packit |
f574b8 |
init->willDelete, init->supportAccessControl,
|
|
Packit |
f574b8 |
init->supportResourceControl);
|
|
Packit |
f574b8 |
buf = writeBitMap(optionsBM, DT_Options, buf, len);
|
|
Packit |
f574b8 |
freeBitMap(optionsBM);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
buf = writeNum(init->PreferredMessageSize,
|
|
Packit |
f574b8 |
DT_PreferredMessageSize,
|
|
Packit |
f574b8 |
buf,
|
|
Packit |
f574b8 |
len);
|
|
Packit |
f574b8 |
buf = writeNum(init->MaximumRecordSize,
|
|
Packit |
f574b8 |
DT_MaximumRecordSize,
|
|
Packit |
f574b8 |
buf,
|
|
Packit |
f574b8 |
len);
|
|
Packit |
f574b8 |
buf = writeString(init->IDAuthentication,
|
|
Packit |
f574b8 |
DT_IDAuthentication,
|
|
Packit |
f574b8 |
buf,
|
|
Packit |
f574b8 |
len);
|
|
Packit |
f574b8 |
buf = writeString(init->ImplementationID,
|
|
Packit |
f574b8 |
DT_ImplementationID,
|
|
Packit |
f574b8 |
buf,
|
|
Packit |
f574b8 |
len);
|
|
Packit |
f574b8 |
buf = writeString(init->ImplementationName,
|
|
Packit |
f574b8 |
DT_ImplementationName,
|
|
Packit |
f574b8 |
buf,
|
|
Packit |
f574b8 |
len);
|
|
Packit |
f574b8 |
buf = writeString(init->ImplementationVersion,
|
|
Packit |
f574b8 |
DT_ImplementationVersion,
|
|
Packit |
f574b8 |
buf,
|
|
Packit |
f574b8 |
len);
|
|
Packit |
f574b8 |
buf = writeAny(init->ReferenceID,
|
|
Packit |
f574b8 |
DT_ReferenceID,
|
|
Packit |
f574b8 |
buf,
|
|
Packit |
f574b8 |
len);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* go back and write the header-length-indicator */
|
|
Packit |
f574b8 |
RELEASE_HEADER_SPACE(len);
|
|
Packit |
f574b8 |
size = buf - buffer - HEADER_LEN;
|
|
Packit |
f574b8 |
writeBinaryInteger(size, HEADER_LEN, buffer, len);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (init->UserInformationField != NULL)
|
|
Packit |
f574b8 |
buf = writeInitResponseInfo(init, buf, len);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (buf);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *readInitResponseAPDU(InitResponseAPDU **init, char *buffer)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char *buf = buffer;
|
|
Packit |
f574b8 |
boolean search, present, delete, accessControl, resourceControl;
|
|
Packit |
f574b8 |
long prefSize, maxMsgSize;
|
|
Packit |
f574b8 |
char *auth, *id, *name, *version;
|
|
Packit |
f574b8 |
long size;
|
|
Packit |
f574b8 |
pdu_type pduType;
|
|
Packit |
f574b8 |
bit_map *versionBM = NULL;
|
|
Packit |
f574b8 |
bit_map *optionsBM = NULL;
|
|
Packit |
f574b8 |
boolean result;
|
|
Packit |
f574b8 |
any *refID = NULL;
|
|
Packit |
f574b8 |
void *userInfo = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
auth = id = name = version = NULL;
|
|
Packit |
f574b8 |
refID = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* read required part */
|
|
Packit |
f574b8 |
buf = readBinaryInteger(&size, HEADER_LEN, buf);
|
|
Packit |
f574b8 |
buf = readPDUType(&pduType, buf);
|
|
Packit |
f574b8 |
buf = readBoolean(&result, buf);
|
|
Packit |
f574b8 |
buf = readBitMap(&versionBM, buf);
|
|
Packit |
f574b8 |
buf = readBitMap(&optionsBM, buf);
|
|
Packit |
f574b8 |
buf = readNum(&prefSize, buf);
|
|
Packit |
f574b8 |
buf = readNum(&maxMsgSize, buf);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* decode optionsBM */
|
|
Packit |
f574b8 |
search = bitAtPos(0, optionsBM);
|
|
Packit |
f574b8 |
present = bitAtPos(1, optionsBM);
|
|
Packit |
f574b8 |
delete = bitAtPos(2, optionsBM);
|
|
Packit |
f574b8 |
accessControl = bitAtPos(3, optionsBM);
|
|
Packit |
f574b8 |
resourceControl = bitAtPos(4, optionsBM);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* read optional part */
|
|
Packit |
f574b8 |
while (buf < (buffer + size + HEADER_LEN)) {
|
|
Packit |
f574b8 |
data_tag tag = peekTag(buf);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
switch (tag) {
|
|
Packit |
f574b8 |
case DT_IDAuthentication:
|
|
Packit |
f574b8 |
buf = readString(&auth, buf);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case DT_ImplementationID:
|
|
Packit |
f574b8 |
buf = readString(&id, buf);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case DT_ImplementationName:
|
|
Packit |
f574b8 |
buf = readString(&name, buf);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case DT_ImplementationVersion:
|
|
Packit |
f574b8 |
buf = readString(&version, buf);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case DT_ReferenceID:
|
|
Packit |
f574b8 |
buf = readAny(&refID, buf);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
default:
|
|
Packit |
f574b8 |
freeBitMap(versionBM);
|
|
Packit |
f574b8 |
freeBitMap(optionsBM);
|
|
Packit |
f574b8 |
s_free(auth);
|
|
Packit |
f574b8 |
s_free(id);
|
|
Packit |
f574b8 |
s_free(name);
|
|
Packit |
f574b8 |
s_free(version);
|
|
Packit |
f574b8 |
freeAny(refID);
|
|
Packit |
f574b8 |
REPORT_READ_ERROR(buf);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
buf = readInitResponseInfo(&userInfo, buf);
|
|
Packit |
f574b8 |
if (buf == NULL) {
|
|
Packit |
f574b8 |
freeBitMap(versionBM);
|
|
Packit |
f574b8 |
freeBitMap(optionsBM);
|
|
Packit |
f574b8 |
s_free(auth);
|
|
Packit |
f574b8 |
s_free(id);
|
|
Packit |
f574b8 |
s_free(name);
|
|
Packit |
f574b8 |
s_free(version);
|
|
Packit |
f574b8 |
freeAny(refID);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
RETURN_ON_NULL(buf);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* construct the basic init object */
|
|
Packit |
f574b8 |
*init = makeInitResponseAPDU(result,
|
|
Packit |
f574b8 |
search,
|
|
Packit |
f574b8 |
present,
|
|
Packit |
f574b8 |
delete,
|
|
Packit |
f574b8 |
accessControl,
|
|
Packit |
f574b8 |
resourceControl,
|
|
Packit |
f574b8 |
prefSize,
|
|
Packit |
f574b8 |
maxMsgSize,
|
|
Packit |
f574b8 |
auth,
|
|
Packit |
f574b8 |
id,
|
|
Packit |
f574b8 |
name,
|
|
Packit |
f574b8 |
version,
|
|
Packit |
f574b8 |
refID,
|
|
Packit |
f574b8 |
userInfo);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
freeBitMap(versionBM);
|
|
Packit |
f574b8 |
freeBitMap(optionsBM);
|
|
Packit |
f574b8 |
s_free(auth);
|
|
Packit |
f574b8 |
s_free(id);
|
|
Packit |
f574b8 |
s_free(name);
|
|
Packit |
f574b8 |
s_free(version);
|
|
Packit |
f574b8 |
freeAny(refID);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (buf);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
InitResponseAPDU *replyToInitAPDU(InitAPDU * init, boolean result, void *userInfo)
|
|
Packit |
f574b8 |
/* respond to an init message in the default way - echoing back
|
|
Packit |
f574b8 |
the init info
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
InitResponseAPDU *initResp;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
initResp = makeInitResponseAPDU(result,
|
|
Packit |
f574b8 |
init->willSearch,
|
|
Packit |
f574b8 |
init->willPresent,
|
|
Packit |
f574b8 |
init->willDelete,
|
|
Packit |
f574b8 |
init->supportAccessControl,
|
|
Packit |
f574b8 |
init->supportResourceControl,
|
|
Packit |
f574b8 |
init->PreferredMessageSize,
|
|
Packit |
f574b8 |
init->MaximumRecordSize,
|
|
Packit |
f574b8 |
init->IDAuthentication,
|
|
Packit |
f574b8 |
defaultImplementationID(),
|
|
Packit |
f574b8 |
defaultImplementationName(),
|
|
Packit |
f574b8 |
defaultImplementationVersion(),
|
|
Packit |
f574b8 |
init->ReferenceID,
|
|
Packit |
f574b8 |
userInfo);
|
|
Packit |
f574b8 |
return (initResp);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
SearchAPDU *makeSearchAPDU(long small,
|
|
Packit |
f574b8 |
long large,
|
|
Packit |
f574b8 |
long medium,
|
|
Packit |
f574b8 |
boolean replace,
|
|
Packit |
f574b8 |
char *name,
|
|
Packit |
f574b8 |
char **databases,
|
|
Packit |
f574b8 |
char *type,
|
|
Packit |
f574b8 |
char **elements,
|
|
Packit |
f574b8 |
any *refID,
|
|
Packit |
f574b8 |
void *queryInfo)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char *ptr = NULL;
|
|
Packit |
f574b8 |
long i;
|
|
Packit |
f574b8 |
SearchAPDU *query = (SearchAPDU *) s_malloc((size_t) sizeof(SearchAPDU));
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
query->PDUType = searchAPDU;
|
|
Packit |
f574b8 |
query->SmallSetUpperBound = small;
|
|
Packit |
f574b8 |
query->LargeSetLowerBound = large;
|
|
Packit |
f574b8 |
query->MediumSetPresentNumber = medium;
|
|
Packit |
f574b8 |
query->ReplaceIndicator = replace;
|
|
Packit |
f574b8 |
query->ResultSetName = s_strdup(name);
|
|
Packit |
f574b8 |
query->DatabaseNames = NULL;
|
|
Packit |
f574b8 |
if (databases != NULL) {
|
|
Packit |
f574b8 |
for (i = 0, ptr = databases[i]; ptr != NULL; ptr = databases[++i]) {
|
|
Packit |
f574b8 |
if (query->DatabaseNames == NULL)
|
|
Packit |
f574b8 |
query->DatabaseNames = (char **) s_malloc((size_t) (sizeof(char
|
|
Packit |
f574b8 |
*)
|
|
Packit |
f574b8 |
* 2));
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
else
|
|
Packit |
f574b8 |
query->DatabaseNames = (char **) s_realloc((char *) query->DatabaseNames,
|
|
Packit |
f574b8 |
(size_t) (sizeof(char
|
|
Packit |
f574b8 |
*) *
|
|
Packit |
f574b8 |
(i + 2)));
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
query->DatabaseNames[i] = s_strdup(ptr);
|
|
Packit |
f574b8 |
query->DatabaseNames[i + 1] = NULL;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
query->QueryType = s_strdup(type);
|
|
Packit |
f574b8 |
query->ElementSetNames = NULL;
|
|
Packit |
f574b8 |
if (elements != NULL) {
|
|
Packit |
f574b8 |
for (i = 0, ptr = elements[i]; ptr != NULL; ptr = elements[++i]) {
|
|
Packit |
f574b8 |
if (query->ElementSetNames == NULL)
|
|
Packit |
f574b8 |
query->ElementSetNames =
|
|
Packit |
f574b8 |
(char **) s_malloc((size_t) (sizeof(char *) * 2));
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
else
|
|
Packit |
f574b8 |
query->ElementSetNames = (char **) s_realloc((char *) query->ElementSetNames,
|
|
Packit |
f574b8 |
(size_t) (sizeof(char
|
|
Packit |
f574b8 |
*) *
|
|
Packit |
f574b8 |
(i + 2)));
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
query->ElementSetNames[i] = s_strdup(ptr);
|
|
Packit |
f574b8 |
query->ElementSetNames[i + 1] = NULL;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
query->ReferenceID = duplicateAny(refID);
|
|
Packit |
f574b8 |
query->Query = queryInfo; /* not copied! */
|
|
Packit |
f574b8 |
return (query);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
void freeSearchAPDU(SearchAPDU *query)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
s_free(query->ResultSetName);
|
|
Packit |
f574b8 |
s_free(query->QueryType);
|
|
Packit |
f574b8 |
doList((void **) query->DatabaseNames, fs_free); /* can't use the macro here ! */
|
|
Packit |
f574b8 |
s_free(query->DatabaseNames);
|
|
Packit |
f574b8 |
doList((void **) query->ElementSetNames, fs_free); /* can't use the macro here ! */
|
|
Packit |
f574b8 |
s_free(query->ElementSetNames);
|
|
Packit |
f574b8 |
freeAny(query->ReferenceID);
|
|
Packit |
f574b8 |
s_free(query);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#define DB_DELIMITER "\037" /* hex 1F occurs between each database name */
|
|
Packit |
f574b8 |
#define ES_DELIMITER_1 "\037" /* separates database name from element name */
|
|
Packit |
f574b8 |
#define ES_DELIMITER_2 "\036" /* hex 1E separates <db,es> groups from one another */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *writeSearchAPDU(SearchAPDU *query, char *buffer, long *len)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char *buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
|
|
Packit |
f574b8 |
long size, i;
|
|
Packit |
f574b8 |
char *ptr = NULL;
|
|
Packit |
f574b8 |
char *scratch = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
RESERVE_SPACE_FOR_HEADER(len);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
buf = writePDUType(query->PDUType, buf, len);
|
|
Packit |
f574b8 |
buf = writeBinaryInteger(query->SmallSetUpperBound, (size_t) 3, buf, len);
|
|
Packit |
f574b8 |
buf = writeBinaryInteger(query->LargeSetLowerBound, (size_t) 3, buf, len);
|
|
Packit |
f574b8 |
buf = writeBinaryInteger(query->MediumSetPresentNumber, (size_t) 3, buf, len);
|
|
Packit |
f574b8 |
buf = writeBoolean(query->ReplaceIndicator, buf, len);
|
|
Packit |
f574b8 |
buf = writeString(query->ResultSetName, DT_ResultSetName, buf, len);
|
|
Packit |
f574b8 |
/* write database names */
|
|
Packit |
f574b8 |
if (query->DatabaseNames != NULL) {
|
|
Packit |
f574b8 |
for (i = 0, scratch = NULL, ptr = query->DatabaseNames[i]; ptr != NULL;
|
|
Packit |
f574b8 |
ptr = query->DatabaseNames[++i]) {
|
|
Packit |
f574b8 |
if (scratch == NULL)
|
|
Packit |
f574b8 |
scratch = s_strdup(ptr);
|
|
Packit |
f574b8 |
else {
|
|
Packit |
f574b8 |
size_t newScratchSize = (size_t) (strlen(scratch) +
|
|
Packit |
f574b8 |
strlen(ptr) + 2);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
scratch = (char *) s_realloc(scratch, newScratchSize);
|
|
Packit |
f574b8 |
s_strncat(scratch, DB_DELIMITER, 2, newScratchSize);
|
|
Packit |
f574b8 |
s_strncat(scratch, ptr, strlen(ptr) + 1, newScratchSize);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
buf = writeString(scratch, DT_DatabaseNames, buf, len);
|
|
Packit |
f574b8 |
s_free(scratch);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
buf = writeString(query->QueryType, DT_QueryType, buf, len);
|
|
Packit |
f574b8 |
/* write element set names */
|
|
Packit |
f574b8 |
if (query->ElementSetNames != NULL) {
|
|
Packit |
f574b8 |
for (i = 0, scratch = NULL, ptr = query->ElementSetNames[i];
|
|
Packit |
f574b8 |
ptr != NULL;
|
|
Packit |
f574b8 |
ptr = query->ElementSetNames[++i]) {
|
|
Packit |
f574b8 |
if (scratch == NULL) {
|
|
Packit |
f574b8 |
if (query->ElementSetNames[i + 1] == NULL) /* there is a single element set name */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
scratch = (char *) s_malloc((size_t) strlen(ptr) + 2);
|
|
Packit |
f574b8 |
StrNCpy(scratch, ES_DELIMITER_1, 2);
|
|
Packit |
f574b8 |
s_strncat(scratch, ptr, strlen(ptr) + 1, strlen(ptr) + 2);
|
|
Packit |
f574b8 |
} else { /* this is the first of a series of element set names */
|
|
Packit |
f574b8 |
size_t newScratchSize = (size_t) (strlen(ptr) +
|
|
Packit |
f574b8 |
strlen(query->ElementSetNames[i
|
|
Packit |
f574b8 |
+ 1])
|
|
Packit |
f574b8 |
+ 2);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
scratch = s_strdup(ptr); /* the database name */
|
|
Packit |
f574b8 |
ptr = query->ElementSetNames[++i]; /* the element set name */
|
|
Packit |
f574b8 |
scratch = (char *) s_realloc(scratch, newScratchSize);
|
|
Packit |
f574b8 |
s_strncat(scratch, ES_DELIMITER_1, 2, newScratchSize);
|
|
Packit |
f574b8 |
s_strncat(scratch, ptr, strlen(ptr) + 1, newScratchSize);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
char *esPtr = query->ElementSetNames[++i]; /* the element set name */
|
|
Packit |
f574b8 |
size_t newScratchSize = (size_t) (strlen(scratch) +
|
|
Packit |
f574b8 |
strlen(ptr) +
|
|
Packit |
f574b8 |
strlen(esPtr) +
|
|
Packit |
f574b8 |
3);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
scratch = (char *) s_realloc(scratch, newScratchSize);
|
|
Packit |
f574b8 |
s_strncat(scratch, ES_DELIMITER_2, 2, newScratchSize);
|
|
Packit |
f574b8 |
s_strncat(scratch, ptr, strlen(ptr) + 1, newScratchSize);
|
|
Packit |
f574b8 |
s_strncat(scratch, ES_DELIMITER_1, 2, newScratchSize);
|
|
Packit |
f574b8 |
s_strncat(scratch, esPtr, strlen(esPtr) + 1, newScratchSize);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
buf = writeString(scratch, DT_ElementSetNames, buf, len);
|
|
Packit |
f574b8 |
s_free(scratch);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
buf = writeAny(query->ReferenceID, DT_ReferenceID, buf, len);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* go back and write the header-length-indicator */
|
|
Packit |
f574b8 |
RELEASE_HEADER_SPACE(len);
|
|
Packit |
f574b8 |
size = buf - buffer - HEADER_LEN;
|
|
Packit |
f574b8 |
writeBinaryInteger(size, HEADER_LEN, buffer, len);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (query->Query != NULL)
|
|
Packit |
f574b8 |
buf = writeSearchInfo(query, buf, len);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (buf);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
SearchResponseAPDU *makeSearchResponseAPDU(long result,
|
|
Packit |
f574b8 |
long count,
|
|
Packit |
f574b8 |
long recordsReturned,
|
|
Packit |
f574b8 |
long nextPos,
|
|
Packit |
f574b8 |
long resultStatus,
|
|
Packit |
f574b8 |
long presentStatus,
|
|
Packit |
f574b8 |
any *refID,
|
|
Packit |
f574b8 |
void *records)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
SearchResponseAPDU *query =
|
|
Packit |
f574b8 |
(SearchResponseAPDU *) s_malloc((size_t) sizeof(SearchResponseAPDU));
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
query->PDUType = searchResponseAPDU;
|
|
Packit |
f574b8 |
query->SearchStatus = result;
|
|
Packit |
f574b8 |
query->ResultCount = count;
|
|
Packit |
f574b8 |
query->NumberOfRecordsReturned = recordsReturned;
|
|
Packit |
f574b8 |
query->NextResultSetPosition = nextPos;
|
|
Packit |
f574b8 |
query->ResultSetStatus = resultStatus;
|
|
Packit |
f574b8 |
query->PresentStatus = presentStatus;
|
|
Packit |
f574b8 |
query->ReferenceID = duplicateAny(refID);
|
|
Packit |
f574b8 |
query->DatabaseDiagnosticRecords = records;
|
|
Packit |
f574b8 |
return (query);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
void freeSearchResponseAPDU(SearchResponseAPDU *queryResponse)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
freeAny(queryResponse->ReferenceID);
|
|
Packit |
f574b8 |
s_free(queryResponse);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *writeSearchResponseAPDU(SearchResponseAPDU *queryResponse, char *buffer,
|
|
Packit |
f574b8 |
long *len)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char *buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
|
|
Packit |
f574b8 |
long size;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
RESERVE_SPACE_FOR_HEADER(len);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
buf = writePDUType(queryResponse->PDUType,
|
|
Packit |
f574b8 |
buf,
|
|
Packit |
f574b8 |
len);
|
|
Packit |
f574b8 |
buf = writeBinaryInteger(queryResponse->SearchStatus,
|
|
Packit |
f574b8 |
(size_t) 1,
|
|
Packit |
f574b8 |
buf,
|
|
Packit |
f574b8 |
len);
|
|
Packit |
f574b8 |
buf = writeBinaryInteger(queryResponse->ResultCount,
|
|
Packit |
f574b8 |
(size_t) 3,
|
|
Packit |
f574b8 |
buf,
|
|
Packit |
f574b8 |
len);
|
|
Packit |
f574b8 |
buf = writeBinaryInteger(queryResponse->NumberOfRecordsReturned,
|
|
Packit |
f574b8 |
(size_t) 3,
|
|
Packit |
f574b8 |
buf,
|
|
Packit |
f574b8 |
len);
|
|
Packit |
f574b8 |
buf = writeBinaryInteger(queryResponse->NextResultSetPosition,
|
|
Packit |
f574b8 |
(size_t) 3,
|
|
Packit |
f574b8 |
buf,
|
|
Packit |
f574b8 |
len);
|
|
Packit |
f574b8 |
buf = writeNum(queryResponse->ResultSetStatus,
|
|
Packit |
f574b8 |
DT_ResultSetStatus,
|
|
Packit |
f574b8 |
buf,
|
|
Packit |
f574b8 |
len);
|
|
Packit |
f574b8 |
buf = writeNum(queryResponse->PresentStatus,
|
|
Packit |
f574b8 |
DT_PresentStatus,
|
|
Packit |
f574b8 |
buf,
|
|
Packit |
f574b8 |
len);
|
|
Packit |
f574b8 |
buf = writeAny(queryResponse->ReferenceID,
|
|
Packit |
f574b8 |
DT_ReferenceID,
|
|
Packit |
f574b8 |
buf,
|
|
Packit |
f574b8 |
len);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* go back and write the header-length-indicator */
|
|
Packit |
f574b8 |
RELEASE_HEADER_SPACE(len);
|
|
Packit |
f574b8 |
size = buf - buffer - HEADER_LEN;
|
|
Packit |
f574b8 |
writeBinaryInteger(size, HEADER_LEN, buffer, len);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (queryResponse->DatabaseDiagnosticRecords != NULL)
|
|
Packit |
f574b8 |
buf = writeSearchResponseInfo(queryResponse, buf, len);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (buf);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *readSearchResponseAPDU(SearchResponseAPDU **queryResponse, char *buffer)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char *buf = buffer;
|
|
Packit |
f574b8 |
long size;
|
|
Packit |
f574b8 |
pdu_type pduType;
|
|
Packit |
f574b8 |
long result, count, recordsReturned, nextPos;
|
|
Packit |
f574b8 |
long resultStatus, presentStatus;
|
|
Packit |
f574b8 |
any *refID = NULL;
|
|
Packit |
f574b8 |
void *userInfo = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* read required part */
|
|
Packit |
f574b8 |
buf = readBinaryInteger(&size, HEADER_LEN, buf);
|
|
Packit |
f574b8 |
buf = readPDUType(&pduType, buf);
|
|
Packit |
f574b8 |
buf = readBinaryInteger(&result, (size_t) 1, buf);
|
|
Packit |
f574b8 |
buf = readBinaryInteger(&count, (size_t) 3, buf);
|
|
Packit |
f574b8 |
buf = readBinaryInteger(&recordsReturned, (size_t) 3, buf);
|
|
Packit |
f574b8 |
buf = readBinaryInteger(&nextPos, (size_t) 3, buf);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
resultStatus = presentStatus = UNUSED;
|
|
Packit |
f574b8 |
refID = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* read optional part */
|
|
Packit |
f574b8 |
while (buf < (buffer + size + HEADER_LEN)) {
|
|
Packit |
f574b8 |
data_tag tag = peekTag(buf);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
switch (tag) {
|
|
Packit |
f574b8 |
case DT_ResultSetStatus:
|
|
Packit |
f574b8 |
buf = readNum(&resultStatus, buf);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case DT_PresentStatus:
|
|
Packit |
f574b8 |
buf = readNum(&presentStatus, buf);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case DT_ReferenceID:
|
|
Packit |
f574b8 |
buf = readAny(&refID, buf);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
default:
|
|
Packit |
f574b8 |
freeAny(refID);
|
|
Packit |
f574b8 |
REPORT_READ_ERROR(buf);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
buf = readSearchResponseInfo(&userInfo, buf);
|
|
Packit |
f574b8 |
if (buf == NULL)
|
|
Packit |
f574b8 |
freeAny(refID);
|
|
Packit |
f574b8 |
RETURN_ON_NULL(buf);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* construct the search object */
|
|
Packit |
f574b8 |
*queryResponse = makeSearchResponseAPDU(result,
|
|
Packit |
f574b8 |
count,
|
|
Packit |
f574b8 |
recordsReturned,
|
|
Packit |
f574b8 |
nextPos,
|
|
Packit |
f574b8 |
(long) resultStatus,
|
|
Packit |
f574b8 |
(long) presentStatus,
|
|
Packit |
f574b8 |
refID,
|
|
Packit |
f574b8 |
userInfo);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
freeAny(refID);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (buf);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Routines originally from ZUtil.c -- FM
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
/* WIDE AREA INFORMATION SERVER SOFTWARE:
|
|
Packit |
f574b8 |
* No guarantees or restrictions. See the readme file for the full standard
|
|
Packit |
f574b8 |
* disclaimer.
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* 3.26.90 Harry Morris, morris@think.com
|
|
Packit |
f574b8 |
* 3.30.90 Harry Morris - Changed any->bits to any->bytes
|
|
Packit |
f574b8 |
* 4.11.90 HWM - fixed include file names, changed
|
|
Packit |
f574b8 |
* - writeCompressedIntegerWithPadding() to
|
|
Packit |
f574b8 |
* writeCompressedIntWithPadding()
|
|
Packit |
f574b8 |
* - generalized conditional includes (see c-dialect.h)
|
|
Packit |
f574b8 |
* 3.7.91 Jonny Goldman. Replaced "short" in makeBitMap with "int" line 632.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *readErrorPosition = NULL; /* pos where buf stoped making sense */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
/* A note on error handling
|
|
Packit |
f574b8 |
read - these are low level routines, they do not check the type tags
|
|
Packit |
f574b8 |
which (sometimes) preceed the data (this is done by the higher
|
|
Packit |
f574b8 |
level functions which call these functions). There is no
|
|
Packit |
f574b8 |
attempt made to check that the reading does not exceed the read
|
|
Packit |
f574b8 |
buffer. Such cases should be very rare and usually will be
|
|
Packit |
f574b8 |
caught by the calling functions. (note - it is unlikely that
|
|
Packit |
f574b8 |
a series of low level reads will go far off the edge without
|
|
Packit |
f574b8 |
triggering a type error. However, it is possible for a single
|
|
Packit |
f574b8 |
bad read in an array function (eg. readAny) to attempt to read a
|
|
Packit |
f574b8 |
large ammount, possibly causing a segmentation violation or out
|
|
Packit |
f574b8 |
of memory condition.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
diagnosticRecord *makeDiag(boolean surrogate, char *code, char *addInfo)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
diagnosticRecord *diag =
|
|
Packit |
f574b8 |
(diagnosticRecord *) s_malloc((size_t) sizeof(diagnosticRecord));
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
diag->SURROGATE = surrogate;
|
|
Packit |
f574b8 |
MemCpy(diag->DIAG, code, DIAGNOSTIC_CODE_SIZE);
|
|
Packit |
f574b8 |
diag->ADDINFO = s_strdup(addInfo);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (diag);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
void freeDiag(diagnosticRecord * diag)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
if (diag != NULL) {
|
|
Packit |
f574b8 |
if (diag->ADDINFO != NULL)
|
|
Packit |
f574b8 |
s_free(diag->ADDINFO);
|
|
Packit |
f574b8 |
s_free(diag);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#define END_OF_RECORD 0x1D
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *writeDiag(diagnosticRecord * diag, char *buffer, long *len)
|
|
Packit |
f574b8 |
/* diagnostics (as per Appendix D) have a very weird format - this changes
|
|
Packit |
f574b8 |
in SR-1
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char *buf = buffer;
|
|
Packit |
f574b8 |
long length;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (diag == NULL) /* handle unspecified optional args */
|
|
Packit |
f574b8 |
return (buf);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
buf = writeTag(DT_DatabaseDiagnosticRecords, buf, len);
|
|
Packit |
f574b8 |
CHECK_FOR_SPACE_LEFT(0, len);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
length = 3;
|
|
Packit |
f574b8 |
if (diag->ADDINFO != NULL)
|
|
Packit |
f574b8 |
length += strlen(diag->ADDINFO);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (length >= 0xFFFF) /* make sure the length is reasonable */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
length = 0xFFFF - 1;
|
|
Packit |
f574b8 |
diag->ADDINFO[0xFFFF - 3 - 1] = '\0';
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
buf = writeBinaryInteger(length, 2, buf, len);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
CHECK_FOR_SPACE_LEFT(1, len);
|
|
Packit |
f574b8 |
buf[0] = diag->DIAG[0];
|
|
Packit |
f574b8 |
buf++;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
CHECK_FOR_SPACE_LEFT(1, len);
|
|
Packit |
f574b8 |
buf[0] = diag->DIAG[1];
|
|
Packit |
f574b8 |
buf++;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (length > 3) {
|
|
Packit |
f574b8 |
CHECK_FOR_SPACE_LEFT(3, len);
|
|
Packit |
f574b8 |
MemCpy(buf, diag->ADDINFO, length - 3);
|
|
Packit |
f574b8 |
buf += length - 3;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
CHECK_FOR_SPACE_LEFT(1, len);
|
|
Packit |
f574b8 |
buf[0] = diag->SURROGATE;
|
|
Packit |
f574b8 |
buf++;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
CHECK_FOR_SPACE_LEFT(1, len);
|
|
Packit |
f574b8 |
buf[0] = END_OF_RECORD;
|
|
Packit |
f574b8 |
buf++;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (buf);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *readDiag(diagnosticRecord ** diag, char *buffer)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char *buf = buffer;
|
|
Packit |
f574b8 |
diagnosticRecord *d = (diagnosticRecord *) s_malloc((size_t) sizeof(diagnosticRecord));
|
|
Packit |
f574b8 |
data_tag tag;
|
|
Packit |
f574b8 |
long len;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
buf = readTag(&tag, buf);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
buf = readBinaryInteger(&len, 2, buf);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
d->DIAG[0] = buf[0];
|
|
Packit |
f574b8 |
d->DIAG[1] = buf[1];
|
|
Packit |
f574b8 |
d->DIAG[2] = '\0';
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (len > 3) {
|
|
Packit |
f574b8 |
d->ADDINFO = (char *) s_malloc((size_t) (len - 3 + 1));
|
|
Packit |
f574b8 |
MemCpy(d->ADDINFO, (char *) (buf + 2), len - 3);
|
|
Packit |
f574b8 |
d->ADDINFO[len - 3] = '\0';
|
|
Packit |
f574b8 |
} else
|
|
Packit |
f574b8 |
d->ADDINFO = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
d->SURROGATE = buf[len - 1];
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
*diag = d;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (buf + len + 1);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#define continueBit 0x80
|
|
Packit |
f574b8 |
#define dataMask 0x7F
|
|
Packit |
f574b8 |
#define dataBits 7
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *writeCompressedInteger(unsigned long num, char *buf, long *len)
|
|
Packit |
f574b8 |
/* write a binary integer in the format described on p. 40.
|
|
Packit |
f574b8 |
this might be sped up
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char byte;
|
|
Packit |
f574b8 |
unsigned long i;
|
|
Packit |
f574b8 |
unsigned long size;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
size = writtenCompressedIntSize(num);
|
|
Packit |
f574b8 |
CHECK_FOR_SPACE_LEFT(size, len);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
for (i = size - 1; i != 0; i--) {
|
|
Packit |
f574b8 |
byte = num & dataMask;
|
|
Packit |
f574b8 |
if (i != (size - 1)) /* turn on continue bit */
|
|
Packit |
f574b8 |
byte = (char) (byte | continueBit);
|
|
Packit |
f574b8 |
buf[i] = byte;
|
|
Packit |
f574b8 |
num = num >> dataBits; /* don't and here */
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (buf + size);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *readCompressedInteger(unsigned long *num, char *buf)
|
|
Packit |
f574b8 |
/* read a binary integer in the format described on p. 40.
|
|
Packit |
f574b8 |
this might be sped up
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
long i = 0;
|
|
Packit |
f574b8 |
unsigned char byte;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
*num = 0;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
do {
|
|
Packit |
f574b8 |
byte = buf[i++];
|
|
Packit |
f574b8 |
*num = *num << dataBits;
|
|
Packit |
f574b8 |
*num += (byte & dataMask);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
while (byte & continueBit);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (buf + i);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#define pad 128 /* high bit is set */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *writeCompressedIntWithPadding(unsigned long num,
|
|
Packit |
f574b8 |
unsigned long size,
|
|
Packit |
f574b8 |
char *buffer,
|
|
Packit |
f574b8 |
long *len)
|
|
Packit |
f574b8 |
/* Like writeCompressedInteger, except writes padding (128) to make
|
|
Packit |
f574b8 |
sure that size bytes are used. This can be read correctly by
|
|
Packit |
f574b8 |
readCompressedInteger()
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char *buf = buffer;
|
|
Packit |
f574b8 |
unsigned long needed, padding;
|
|
Packit |
f574b8 |
long i;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
CHECK_FOR_SPACE_LEFT(size, len);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
needed = writtenCompressedIntSize(num);
|
|
Packit |
f574b8 |
padding = size - needed;
|
|
Packit |
f574b8 |
i = padding - 1;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
for (i = padding - 1; i >= 0; i--) {
|
|
Packit |
f574b8 |
buf[i] = pad;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
buf = writeCompressedInteger(num, buf + padding, len);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (buf);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
unsigned long writtenCompressedIntSize(unsigned long num)
|
|
Packit |
f574b8 |
/* return the number of bytes needed to represnet the value num in
|
|
Packit |
f574b8 |
compressed format. curently limited to 4 bytes
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
if (num < CompressedInt1Byte)
|
|
Packit |
f574b8 |
return (1);
|
|
Packit |
f574b8 |
else if (num < CompressedInt2Byte)
|
|
Packit |
f574b8 |
return (2);
|
|
Packit |
f574b8 |
else if (num < CompressedInt3Byte)
|
|
Packit |
f574b8 |
return (3);
|
|
Packit |
f574b8 |
else
|
|
Packit |
f574b8 |
return (4);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *writeTag(data_tag tag, char *buf, long *len)
|
|
Packit |
f574b8 |
/* write out a data tag */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
return (writeCompressedInteger(tag, buf, len));
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *readTag(data_tag *tag, char *buf)
|
|
Packit |
f574b8 |
/* read a data tag */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
return (readCompressedInteger(tag, buf));
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
unsigned long writtenTagSize(data_tag tag)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
return (writtenCompressedIntSize(tag));
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
data_tag peekTag(char *buf)
|
|
Packit |
f574b8 |
/* read a data tag without advancing the buffer */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
data_tag tag;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
readTag(&tag, buf);
|
|
Packit |
f574b8 |
return (tag);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
any *makeAny(unsigned long size, char *data)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
any *a = (any *) s_malloc((size_t) sizeof(any));
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
a->size = size;
|
|
Packit |
f574b8 |
a->bytes = data;
|
|
Packit |
f574b8 |
return (a);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
void freeAny(any *a)
|
|
Packit |
f574b8 |
/* destroy an any and its associated data. Assumes a->bytes was
|
|
Packit |
f574b8 |
allocated using the s_malloc family of libraries
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
if (a != NULL) {
|
|
Packit |
f574b8 |
if (a->bytes != NULL)
|
|
Packit |
f574b8 |
s_free(a->bytes);
|
|
Packit |
f574b8 |
s_free(a);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
any *duplicateAny(any *a)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
any *copy = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (a == NULL)
|
|
Packit |
f574b8 |
return (NULL);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
copy = (any *) s_malloc((size_t) sizeof(any));
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
copy->size = a->size;
|
|
Packit |
f574b8 |
if (a->bytes == NULL)
|
|
Packit |
f574b8 |
copy->bytes = NULL;
|
|
Packit |
f574b8 |
else {
|
|
Packit |
f574b8 |
copy->bytes = (char *) s_malloc((size_t) copy->size);
|
|
Packit |
f574b8 |
MemCpy(copy->bytes, a->bytes, copy->size);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
return (copy);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *writeAny(any *a, data_tag tag, char *buffer, long *len)
|
|
Packit |
f574b8 |
/* write an any + tag and size info */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char *buf = buffer;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (a == NULL) /* handle unspecified optional args */
|
|
Packit |
f574b8 |
return (buf);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* write the tags */
|
|
Packit |
f574b8 |
buf = writeTag(tag, buf, len);
|
|
Packit |
f574b8 |
buf = writeCompressedInteger(a->size, buf, len);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* write the bytes */
|
|
Packit |
f574b8 |
CHECK_FOR_SPACE_LEFT(a->size, len);
|
|
Packit |
f574b8 |
MemCpy(buf, a->bytes, a->size);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (buf + a->size);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *readAny(any **anAny, char *buffer)
|
|
Packit |
f574b8 |
/* read an any + tag and size info */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char *buf;
|
|
Packit |
f574b8 |
any *a;
|
|
Packit |
f574b8 |
data_tag tag;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
a = (any *) s_malloc((size_t) sizeof(any));
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
buf = buffer;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
buf = readTag(&tag, buf);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
buf = readCompressedInteger(&a->size, buf);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* now simply copy the bytes */
|
|
Packit |
f574b8 |
a->bytes = (char *) s_malloc((size_t) a->size);
|
|
Packit |
f574b8 |
MemCpy(a->bytes, buf, a->size);
|
|
Packit |
f574b8 |
*anAny = a;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (buf + a->size);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
unsigned long writtenAnySize(data_tag tag, any *a)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
unsigned long size;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (a == NULL)
|
|
Packit |
f574b8 |
return (0);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
size = writtenTagSize(tag);
|
|
Packit |
f574b8 |
size += writtenCompressedIntSize(a->size);
|
|
Packit |
f574b8 |
size += a->size;
|
|
Packit |
f574b8 |
return (size);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
any *stringToAny(char *s)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
any *a = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (s == NULL)
|
|
Packit |
f574b8 |
return (NULL);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
a = (any *) s_malloc((size_t) sizeof(any));
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
a->size = strlen(s);
|
|
Packit |
f574b8 |
a->bytes = (char *) s_malloc((size_t) a->size);
|
|
Packit |
f574b8 |
MemCpy(a->bytes, s, a->size);
|
|
Packit |
f574b8 |
return (a);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *anyToString(any *a)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char *s = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (a == NULL)
|
|
Packit |
f574b8 |
return (NULL);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
s = s_malloc((size_t) (a->size + 1));
|
|
Packit |
f574b8 |
MemCpy(s, a->bytes, a->size);
|
|
Packit |
f574b8 |
s[a->size] = '\0';
|
|
Packit |
f574b8 |
return (s);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *writeString(char *s, data_tag tag, char *buffer, long *len)
|
|
Packit |
f574b8 |
/* Write a C style string. The terminating null is not written.
|
|
Packit |
f574b8 |
This function is not part of the Z39.50 spec. It is provided
|
|
Packit |
f574b8 |
for the convienience of those wishing to pass C strings in
|
|
Packit |
f574b8 |
the place of an any.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char *buf = buffer;
|
|
Packit |
f574b8 |
any *data = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (s == NULL)
|
|
Packit |
f574b8 |
return (buffer); /* handle unused optional item before making an any */
|
|
Packit |
f574b8 |
data = (any *) s_malloc((size_t) sizeof(any));
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
data->size = strlen(s);
|
|
Packit |
f574b8 |
data->bytes = s; /* save a copy here by not using stringToAny() */
|
|
Packit |
f574b8 |
buf = writeAny(data, tag, buf, len);
|
|
Packit |
f574b8 |
s_free(data); /* don't use freeAny() since it will free s too */
|
|
Packit |
f574b8 |
return (buf);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *readString(char **s, char *buffer)
|
|
Packit |
f574b8 |
/* Read an any and convert it into a C style string.
|
|
Packit |
f574b8 |
This function is not part of the Z39.50 spec. It is provided
|
|
Packit |
f574b8 |
for the convienience of those wishing to pass C strings in
|
|
Packit |
f574b8 |
the place of an any.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
any *data = NULL;
|
|
Packit |
f574b8 |
char *buf = readAny(&data, buffer);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
*s = anyToString(data);
|
|
Packit |
f574b8 |
freeAny(data);
|
|
Packit |
f574b8 |
return (buf);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
unsigned long writtenStringSize(data_tag tag, char *s)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
unsigned long size;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (s == NULL)
|
|
Packit |
f574b8 |
return (0);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
size = writtenTagSize(tag);
|
|
Packit |
f574b8 |
size += writtenCompressedIntSize(size);
|
|
Packit |
f574b8 |
size += strlen(s);
|
|
Packit |
f574b8 |
return (size);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
any *longToAny(long num)
|
|
Packit |
f574b8 |
/* a convienience function */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char s[40];
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
sprintf(s, "%ld", num);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (stringToAny(s));
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
long anyToLong(any *a)
|
|
Packit |
f574b8 |
/* a convienience function */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
long num;
|
|
Packit |
f574b8 |
char *str = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
str = anyToString(a);
|
|
Packit |
f574b8 |
sscanf(str, "%ld", &num); /* could check the result and return
|
|
Packit |
f574b8 |
an error */
|
|
Packit |
f574b8 |
s_free(str);
|
|
Packit |
f574b8 |
return (num);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#define bitsPerByte 8
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
bit_map *makeBitMap(unsigned long numBits,...)
|
|
Packit |
f574b8 |
/* construct and return a bitmap with numBits elements */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
va_list ap;
|
|
Packit |
f574b8 |
unsigned long i, j;
|
|
Packit |
f574b8 |
bit_map *bm = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
LYva_start(ap, numBits);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
bm = (bit_map *) s_malloc((size_t) sizeof(bit_map));
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
bm->size = (unsigned long) (ceil((double) numBits / bitsPerByte));
|
|
Packit |
f574b8 |
bm->bytes = (char *) s_malloc((size_t) bm->size);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* fill up the bits */
|
|
Packit |
f574b8 |
for (i = 0; i < bm->size; i++) /* iterate over bytes */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char byte = 0;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
for (j = 0; j < bitsPerByte; j++) /* iterate over bits */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
if ((i * bitsPerByte + j) < numBits) {
|
|
Packit |
f574b8 |
boolean bit = false;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
bit = (boolean) va_arg(ap, boolean);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (bit) {
|
|
Packit |
f574b8 |
byte = byte | (1 << (bitsPerByte - j - 1));
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
bm->bytes[i] = byte;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
va_end(ap);
|
|
Packit |
f574b8 |
return (bm);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
void freeBitMap(bit_map *bm)
|
|
Packit |
f574b8 |
/* destroy a bit map created by makeBitMap() */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
s_free(bm->bytes);
|
|
Packit |
f574b8 |
s_free(bm);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* use this routine to interpret a bit map. pos specifies the bit
|
|
Packit |
f574b8 |
number. bit 0 is the Leftmost bit of the first byte.
|
|
Packit |
f574b8 |
Could do bounds checking.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
boolean bitAtPos(unsigned long pos, bit_map *bm)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
if (pos > bm->size * bitsPerByte)
|
|
Packit |
f574b8 |
return false;
|
|
Packit |
f574b8 |
else
|
|
Packit |
f574b8 |
return ((bm->bytes[(pos / bitsPerByte)] &
|
|
Packit |
f574b8 |
(0x80 >> (pos % bitsPerByte))) ?
|
|
Packit |
f574b8 |
true : false);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *writeBitMap(bit_map *bm, data_tag tag, char *buffer, long *len)
|
|
Packit |
f574b8 |
/* write a bitmap + type and size info */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
return (writeAny((any *) bm, tag, buffer, len));
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *readBitMap(bit_map **bm, char *buffer)
|
|
Packit |
f574b8 |
/* read a bitmap + type and size info */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char *c;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
c = readAny((any **) bm, buffer);
|
|
Packit |
f574b8 |
return (c);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *writeByte(unsigned long byte, char *buf, long *len)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
CHECK_FOR_SPACE_LEFT(1, len);
|
|
Packit |
f574b8 |
buf[0] = byte & 0xFF; /* we really only want the first byte */
|
|
Packit |
f574b8 |
return (buf + 1);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *readByte(unsigned char *byte, char *buf)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
*byte = buf[0];
|
|
Packit |
f574b8 |
return (buf + 1);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *writeBoolean(boolean flag, char *buf, long *len)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
return (writeByte(flag, buf, len));
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *readBoolean(boolean *flag, char *buffer)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
unsigned char byte;
|
|
Packit |
f574b8 |
char *buf = readByte(&byte, buffer);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
*flag = (byte == true) ? true : false;
|
|
Packit |
f574b8 |
return (buf);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *writePDUType(pdu_type pduType, char *buf, long *len)
|
|
Packit |
f574b8 |
/* PDUType is a single byte */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
return (writeBinaryInteger((long) pduType, (unsigned long) 1, buf, len));
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *readPDUType(pdu_type *pduType, char *buf)
|
|
Packit |
f574b8 |
/* PDUType is a single byte */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
return (readBinaryInteger((long *) pduType, (unsigned long) 1, buf));
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
pdu_type peekPDUType(char *buf)
|
|
Packit |
f574b8 |
/* read the next pdu without advancing the buffer, Note that this
|
|
Packit |
f574b8 |
function is to be used on a buffer that is known to contain an
|
|
Packit |
f574b8 |
APDU. The pdu_type is written HEADER_LEN bytes into the buffer
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
pdu_type pdu;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
readPDUType(&pdu, buf + HEADER_LEN);
|
|
Packit |
f574b8 |
return (pdu);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#define BINARY_INTEGER_BYTES sizeof(long) /* the number of bytes used by
|
|
Packit |
f574b8 |
a "binary integer" */
|
|
Packit |
f574b8 |
char *writeBinaryInteger(long num, unsigned long size, char *buf, long *len)
|
|
Packit |
f574b8 |
/* write out first size bytes of num - no type info
|
|
Packit |
f574b8 |
XXX should this take unsigned longs instead ??? */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
long i;
|
|
Packit |
f574b8 |
char byte;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (size < 1 || size > BINARY_INTEGER_BYTES)
|
|
Packit |
f574b8 |
return (NULL); /* error */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
CHECK_FOR_SPACE_LEFT(size, len);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
for (i = size - 1; i >= 0; i--) {
|
|
Packit |
f574b8 |
byte = (char) (num & 255);
|
|
Packit |
f574b8 |
buf[i] = byte;
|
|
Packit |
f574b8 |
num = num >> bitsPerByte; /* don't and here */
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (buf + size);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *readBinaryInteger(long *num, unsigned long size, char *buf)
|
|
Packit |
f574b8 |
/* read in first size bytes of num - no type info
|
|
Packit |
f574b8 |
XXX this should take unsigned longs instead !!! */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
unsigned long i;
|
|
Packit |
f574b8 |
unsigned char byte;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (size < 1 || size > BINARY_INTEGER_BYTES)
|
|
Packit |
f574b8 |
return (buf); /* error */
|
|
Packit |
f574b8 |
*num = 0;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
for (i = 0; i < size; i++) {
|
|
Packit |
f574b8 |
byte = buf[i];
|
|
Packit |
f574b8 |
*num = *num << bitsPerByte;
|
|
Packit |
f574b8 |
*num += byte;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (buf + size);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
unsigned long writtenCompressedBinIntSize(long num)
|
|
Packit |
f574b8 |
/* return the number of bytes needed to represent the value num.
|
|
Packit |
f574b8 |
currently limited to max of 4 bytes
|
|
Packit |
f574b8 |
Only compresses for positive nums - negatives get whole 4 bytes
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
if (num < 0L)
|
|
Packit |
f574b8 |
return (4);
|
|
Packit |
f574b8 |
else if (num < 256L) /* 2**8 */
|
|
Packit |
f574b8 |
return (1);
|
|
Packit |
f574b8 |
else if (num < 65536L) /* 2**16 */
|
|
Packit |
f574b8 |
return (2);
|
|
Packit |
f574b8 |
else if (num < 16777216L) /* 2**24 */
|
|
Packit |
f574b8 |
return (3);
|
|
Packit |
f574b8 |
else
|
|
Packit |
f574b8 |
return (4);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *writeNum(long num, data_tag tag, char *buffer, long *len)
|
|
Packit |
f574b8 |
/* write a binary integer + size and tag info */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char *buf = buffer;
|
|
Packit |
f574b8 |
long size = writtenCompressedBinIntSize(num);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (num == UNUSED)
|
|
Packit |
f574b8 |
return (buffer);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
buf = writeTag(tag, buf, len);
|
|
Packit |
f574b8 |
buf = writeCompressedInteger(size, buf, len);
|
|
Packit |
f574b8 |
buf = writeBinaryInteger(num, (unsigned long) size, buf, len);
|
|
Packit |
f574b8 |
return (buf);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *readNum(long *num, char *buffer)
|
|
Packit |
f574b8 |
/* read a binary integer + size and tag info */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char *buf = buffer;
|
|
Packit |
f574b8 |
data_tag tag;
|
|
Packit |
f574b8 |
unsigned long size;
|
|
Packit |
f574b8 |
unsigned long val;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
buf = readTag(&tag, buf);
|
|
Packit |
f574b8 |
buf = readCompressedInteger(&val, buf);
|
|
Packit |
f574b8 |
size = (unsigned long) val;
|
|
Packit |
f574b8 |
buf = readBinaryInteger(num, size, buf);
|
|
Packit |
f574b8 |
return (buf);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
unsigned long writtenNumSize(data_tag tag, long num)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
long dataSize = writtenCompressedBinIntSize(num);
|
|
Packit |
f574b8 |
long size;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
size = writtenTagSize(tag); /* space for the tag */
|
|
Packit |
f574b8 |
size += writtenCompressedIntSize(dataSize); /* space for the size */
|
|
Packit |
f574b8 |
size += dataSize; /* space for the data */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (size);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
typedef void (voidfunc) (void *);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
void doList(void **list, voidfunc * func)
|
|
Packit |
f574b8 |
/* call func on each element of the NULL terminated list of pointers */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
register long i;
|
|
Packit |
f574b8 |
register void *ptr = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (list == NULL)
|
|
Packit |
f574b8 |
return;
|
|
Packit |
f574b8 |
for (i = 0, ptr = list[i]; ptr != NULL; ptr = list[++i])
|
|
Packit |
f574b8 |
(*func) (ptr);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *writeProtocolVersion(char *buf, long *len)
|
|
Packit |
f574b8 |
/* write a bitmap describing the protocols available */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
static bit_map *version = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (version == NULL) {
|
|
Packit |
f574b8 |
version = makeBitMap((unsigned long) 1, true); /* version 1! */
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (writeBitMap(version, DT_ProtocolVersion, buf, len));
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *defaultImplementationID(void)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
static char ImplementationID[] = "TMC";
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (ImplementationID);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *defaultImplementationName(void)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
static char ImplementationName[] = "Thinking Machines Corporation Z39.50";
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (ImplementationName);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *defaultImplementationVersion(void)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
static char ImplementationVersion[] = "2.0A";
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (ImplementationVersion);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Routines originally from ZType1.c -- FM
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
/* WIDE AREA INFORMATION SERVER SOFTWARE:
|
|
Packit |
f574b8 |
* No guarantees or restrictions. See the readme file for the full standard
|
|
Packit |
f574b8 |
* disclaimer.
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* 3.26.90 Harry Morris, morris@think.com
|
|
Packit |
f574b8 |
* 4.11.90 HWM - generalized conditional includes (see c-dialect.h)
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
query_term *makeAttributeTerm(char *use,
|
|
Packit |
f574b8 |
char *relation,
|
|
Packit |
f574b8 |
char *position,
|
|
Packit |
f574b8 |
char *structure,
|
|
Packit |
f574b8 |
char *truncation,
|
|
Packit |
f574b8 |
char *completeness,
|
|
Packit |
f574b8 |
any *term)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
query_term *qt = (query_term *) s_malloc((size_t) sizeof(query_term));
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
qt->TermType = TT_Attribute;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* copy in the attributes */
|
|
Packit |
f574b8 |
LYStrNCpy(qt->Use, use, ATTRIBUTE_SIZE);
|
|
Packit |
f574b8 |
LYStrNCpy(qt->Relation, relation, ATTRIBUTE_SIZE);
|
|
Packit |
f574b8 |
LYStrNCpy(qt->Position, position, ATTRIBUTE_SIZE);
|
|
Packit |
f574b8 |
LYStrNCpy(qt->Structure, structure, ATTRIBUTE_SIZE);
|
|
Packit |
f574b8 |
LYStrNCpy(qt->Truncation, truncation, ATTRIBUTE_SIZE);
|
|
Packit |
f574b8 |
LYStrNCpy(qt->Completeness, completeness, ATTRIBUTE_SIZE);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
qt->Term = duplicateAny(term);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
qt->ResultSetID = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (qt);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
query_term *makeResultSetTerm(any *resultSet)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
query_term *qt = (query_term *) s_malloc((size_t) sizeof(query_term));
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
qt->TermType = TT_ResultSetID;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
qt->ResultSetID = duplicateAny(resultSet);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
qt->Term = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (qt);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
query_term *makeOperatorTerm(char *operatorCode)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
query_term *qt = (query_term *) s_malloc((size_t) sizeof(query_term));
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
qt->TermType = TT_Operator;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
LYStrNCpy(qt->Operator, operatorCode, OPERATOR_SIZE);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
qt->Term = NULL;
|
|
Packit |
f574b8 |
qt->ResultSetID = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (qt);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
void freeTerm(void *param)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
query_term *qt = (query_term *) param;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
switch (qt->TermType) {
|
|
Packit |
f574b8 |
case TT_Attribute:
|
|
Packit |
f574b8 |
freeAny(qt->Term);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case TT_ResultSetID:
|
|
Packit |
f574b8 |
freeAny(qt->ResultSetID);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case TT_Operator:
|
|
Packit |
f574b8 |
/* do nothing */
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
default:
|
|
Packit |
f574b8 |
panic("Implementation error: Unknown term type %ld",
|
|
Packit |
f574b8 |
qt->TermType);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
s_free(qt);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#define ATTRIBUTE_LIST_SIZE ATTRIBUTE_SIZE * 6
|
|
Packit |
f574b8 |
#define AT_DELIMITER " "
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *writeQueryTerm(query_term *qt, char *buffer, long *len)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char *buf = buffer;
|
|
Packit |
f574b8 |
char attributes[ATTRIBUTE_LIST_SIZE];
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
switch (qt->TermType) {
|
|
Packit |
f574b8 |
case TT_Attribute:
|
|
Packit |
f574b8 |
LYStrNCpy(attributes, qt->Use, ATTRIBUTE_LIST_SIZE);
|
|
Packit |
f574b8 |
s_strncat(attributes, AT_DELIMITER, sizeof(AT_DELIMITER) + 1, ATTRIBUTE_LIST_SIZE);
|
|
Packit |
f574b8 |
s_strncat(attributes, qt->Relation, ATTRIBUTE_SIZE, ATTRIBUTE_LIST_SIZE);
|
|
Packit |
f574b8 |
s_strncat(attributes, AT_DELIMITER, sizeof(AT_DELIMITER) + 1, ATTRIBUTE_LIST_SIZE);
|
|
Packit |
f574b8 |
s_strncat(attributes, qt->Position, ATTRIBUTE_SIZE, ATTRIBUTE_LIST_SIZE);
|
|
Packit |
f574b8 |
s_strncat(attributes, AT_DELIMITER, sizeof(AT_DELIMITER) + 1, ATTRIBUTE_LIST_SIZE);
|
|
Packit |
f574b8 |
s_strncat(attributes, qt->Structure, ATTRIBUTE_SIZE, ATTRIBUTE_LIST_SIZE);
|
|
Packit |
f574b8 |
s_strncat(attributes, AT_DELIMITER, sizeof(AT_DELIMITER) + 1, ATTRIBUTE_LIST_SIZE);
|
|
Packit |
f574b8 |
s_strncat(attributes, qt->Truncation, ATTRIBUTE_SIZE, ATTRIBUTE_LIST_SIZE);
|
|
Packit |
f574b8 |
s_strncat(attributes, AT_DELIMITER, sizeof(AT_DELIMITER) + 1, ATTRIBUTE_LIST_SIZE);
|
|
Packit |
f574b8 |
s_strncat(attributes, qt->Completeness, ATTRIBUTE_SIZE, ATTRIBUTE_LIST_SIZE);
|
|
Packit |
f574b8 |
buf = writeString(attributes, DT_AttributeList, buf, len);
|
|
Packit |
f574b8 |
buf = writeAny(qt->Term, DT_Term, buf, len);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case TT_ResultSetID:
|
|
Packit |
f574b8 |
buf = writeAny(qt->ResultSetID, DT_ResultSetID, buf, len);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case TT_Operator:
|
|
Packit |
f574b8 |
buf = writeString(qt->Operator, DT_Operator, buf, len);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
default:
|
|
Packit |
f574b8 |
panic("Implementation error: Unknown term type %ld",
|
|
Packit |
f574b8 |
qt->TermType);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (buf);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *readQueryTerm(query_term **qt, char *buffer)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char *buf = buffer;
|
|
Packit |
f574b8 |
char *attributeList = NULL;
|
|
Packit |
f574b8 |
char *operator = NULL;
|
|
Packit |
f574b8 |
any *term;
|
|
Packit |
f574b8 |
char *use = NULL;
|
|
Packit |
f574b8 |
char *relation = NULL;
|
|
Packit |
f574b8 |
char *position = NULL;
|
|
Packit |
f574b8 |
char *structure = NULL;
|
|
Packit |
f574b8 |
char *truncation = NULL;
|
|
Packit |
f574b8 |
char *completeness;
|
|
Packit |
f574b8 |
any *resultSetID = NULL;
|
|
Packit |
f574b8 |
data_tag tag;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
tag = peekTag(buffer);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
switch (tag) {
|
|
Packit |
f574b8 |
case DT_AttributeList:
|
|
Packit |
f574b8 |
buf = readString(&attributeList, buf);
|
|
Packit |
f574b8 |
buf = readAny(&term, buf);
|
|
Packit |
f574b8 |
use = strtok(attributeList, AT_DELIMITER);
|
|
Packit |
f574b8 |
relation = strtok(NULL, AT_DELIMITER);
|
|
Packit |
f574b8 |
position = strtok(NULL, AT_DELIMITER);
|
|
Packit |
f574b8 |
structure = strtok(NULL, AT_DELIMITER);
|
|
Packit |
f574b8 |
truncation = strtok(NULL, AT_DELIMITER);
|
|
Packit |
f574b8 |
completeness = strtok(NULL, AT_DELIMITER);
|
|
Packit |
f574b8 |
*qt = makeAttributeTerm(use, relation, position, structure,
|
|
Packit |
f574b8 |
truncation, completeness, term);
|
|
Packit |
f574b8 |
s_free(attributeList);
|
|
Packit |
f574b8 |
freeAny(term);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case DT_ResultSetID:
|
|
Packit |
f574b8 |
buf = readAny(&resultSetID, buf);
|
|
Packit |
f574b8 |
*qt = makeResultSetTerm(resultSetID);
|
|
Packit |
f574b8 |
freeAny(resultSetID);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case DT_Operator:
|
|
Packit |
f574b8 |
buf = readString(&operator, buf);
|
|
Packit |
f574b8 |
*qt = makeOperatorTerm(operator);
|
|
Packit |
f574b8 |
s_free(operator);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
default:
|
|
Packit |
f574b8 |
REPORT_READ_ERROR(buf);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (buf);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
static unsigned long getQueryTermSize(query_term *qt);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
static unsigned long getQueryTermSize(query_term *qt)
|
|
Packit |
f574b8 |
/* figure out how many bytes it will take to write this query */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
unsigned long size = 0;
|
|
Packit |
f574b8 |
static char attributes[] = "11 22 33 44 55 66"; /* we just need this to
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
calculate its written
|
|
Packit |
f574b8 |
size */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
switch (qt->TermType) {
|
|
Packit |
f574b8 |
case TT_Attribute:
|
|
Packit |
f574b8 |
size = writtenStringSize(DT_AttributeList, attributes);
|
|
Packit |
f574b8 |
size += writtenAnySize(DT_Term, qt->Term);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case TT_ResultSetID:
|
|
Packit |
f574b8 |
size = writtenAnySize(DT_ResultSetID, qt->ResultSetID);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
case TT_Operator:
|
|
Packit |
f574b8 |
size = writtenStringSize(DT_Operator, qt->Operator);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
default:
|
|
Packit |
f574b8 |
panic("Implementation error: Unknown term type %ld",
|
|
Packit |
f574b8 |
qt->TermType);
|
|
Packit |
f574b8 |
break;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (size);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* A query is simply a null terminated list of query terms. For
|
|
Packit |
f574b8 |
transmission, a query is written into an any which is sent as
|
|
Packit |
f574b8 |
the user information field. */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
any *writeQuery(query_term **terms)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
any *info = NULL;
|
|
Packit |
f574b8 |
char *writePos = NULL;
|
|
Packit |
f574b8 |
char *data = NULL;
|
|
Packit |
f574b8 |
unsigned long size = 0;
|
|
Packit |
f574b8 |
long remaining = 0;
|
|
Packit |
f574b8 |
long i;
|
|
Packit |
f574b8 |
query_term *qt = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (terms == NULL)
|
|
Packit |
f574b8 |
return (NULL);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* calculate the size of write buffer */
|
|
Packit |
f574b8 |
for (i = 0, qt = terms[i]; qt != NULL; qt = terms[++i])
|
|
Packit |
f574b8 |
size += getQueryTermSize(qt);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
data = (char *) s_malloc((size_t) size);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* write the terms */
|
|
Packit |
f574b8 |
writePos = data;
|
|
Packit |
f574b8 |
remaining = size;
|
|
Packit |
f574b8 |
for (i = 0, qt = terms[i]; qt != NULL; qt = terms[++i])
|
|
Packit |
f574b8 |
writePos = writeQueryTerm(qt, writePos, &remaining);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
info = makeAny(size, data);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (info);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
query_term **readQuery(any *info)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
char *readPos = info->bytes;
|
|
Packit |
f574b8 |
query_term **terms = NULL;
|
|
Packit |
f574b8 |
query_term *qt = NULL;
|
|
Packit |
f574b8 |
long numTerms = 0L;
|
|
Packit |
f574b8 |
char tmp[100];
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
sprintf(tmp, "readquery: bytes: %ld", info->size);
|
|
Packit |
f574b8 |
log_write(tmp);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
while (readPos < info->bytes + info->size) {
|
|
Packit |
f574b8 |
readPos = readQueryTerm(&qt, readPos);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (terms == NULL) {
|
|
Packit |
f574b8 |
terms = (query_term **) s_malloc((size_t) (sizeof(query_term *) * 2));
|
|
Packit |
f574b8 |
} else {
|
|
Packit |
f574b8 |
terms =
|
|
Packit |
f574b8 |
(query_term **) s_realloc((char *) terms,
|
|
Packit |
f574b8 |
(size_t) (sizeof(query_term *) *
|
|
Packit |
f574b8 |
(numTerms + 2)));
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
if (qt == NULL)
|
|
Packit |
f574b8 |
log_write("qt = null");
|
|
Packit |
f574b8 |
terms[numTerms++] = qt;
|
|
Packit |
f574b8 |
terms[numTerms] = NULL;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (terms);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Routines originally from panic.c -- FM
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
/* WIDE AREA INFORMATION SERVER SOFTWARE:
|
|
Packit |
f574b8 |
* No guarantees or restrictions. See the readme file for the full standard
|
|
Packit |
f574b8 |
* disclaimer.
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* Morris@think.com
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* panic is an error system interface. On the Mac, it will pop
|
|
Packit |
f574b8 |
* up a little window to explain the problem.
|
|
Packit |
f574b8 |
* On a unix box, it will print out the error and call perror()
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
static void exitAction(long error);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
static void exitAction(long error GCC_UNUSED)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
exit_immediately(EXIT_SUCCESS);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
#define PANIC_HEADER "Fatal Error: "
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
void panic(char *format,...)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
va_list ap; /* the variable arguments */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
fprintf(stderr, PANIC_HEADER);
|
|
Packit |
f574b8 |
LYva_start(ap, format); /* init ap */
|
|
Packit |
f574b8 |
vfprintf(stderr, format, ap); /* print the contents */
|
|
Packit |
f574b8 |
va_end(ap); /* free ap */
|
|
Packit |
f574b8 |
fflush(stderr);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
exitAction(0);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*
|
|
Packit |
f574b8 |
* Routines originally from cutil.c -- FM
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
/* Wide AREA INFORMATION SERVER SOFTWARE
|
|
Packit |
f574b8 |
* No guarantees or restrictions. See the readme file for the full standard
|
|
Packit |
f574b8 |
* disclaimer.
|
|
Packit |
f574b8 |
*
|
|
Packit |
f574b8 |
* 3.26.90 Harry Morris, morris@think.com
|
|
Packit |
f574b8 |
* 4.11.90 HWM - generalized conditional includes (see c-dialect.h)
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
void fs_checkPtr(void *ptr)
|
|
Packit |
f574b8 |
/* If the ptr is NULL, give an error */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
if (ptr == NULL)
|
|
Packit |
f574b8 |
panic("checkPtr found a NULL pointer");
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
void *fs_malloc(size_t size)
|
|
Packit |
f574b8 |
/* does safety checks and optional accounting */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
register void *ptr = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
ptr = (void *) calloc((size_t) size, (size_t) 1);
|
|
Packit |
f574b8 |
s_checkPtr(ptr);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (ptr);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
void *fs_realloc(void *ptr, size_t size)
|
|
Packit |
f574b8 |
/* does safety checks and optional accounting
|
|
Packit |
f574b8 |
note - we don't know how big ptr's memory is, so we can't ensure
|
|
Packit |
f574b8 |
that any new memory allocated is NULLed!
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
register void *nptr = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (ptr == NULL) /* this is really a malloc */
|
|
Packit |
f574b8 |
return (s_malloc(size));
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
nptr = (void *) realloc(ptr, size);
|
|
Packit |
f574b8 |
s_checkPtr(ptr);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
return (nptr);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
void fs_free(void *ptr)
|
|
Packit |
f574b8 |
/* does safety checks and optional accounting */
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
if (ptr != NULL) /* some non-ansi compilers/os's cant handle freeing null */
|
|
Packit |
f574b8 |
{ /* if we knew the size of this block of memory, we could clear it - oh well */
|
|
Packit |
f574b8 |
free(ptr);
|
|
Packit |
f574b8 |
ptr = NULL;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *s_strdup(char *s)
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* return a copy of s. This is identical to the standard library routine
|
|
Packit |
f574b8 |
strdup(), except that it is safe. If s == NULL or malloc fails,
|
|
Packit |
f574b8 |
appropriate action is taken.
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
unsigned long len;
|
|
Packit |
f574b8 |
char *copy = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (s == NULL) /* saftey check to postpone stupid errors */
|
|
Packit |
f574b8 |
return (NULL);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
len = strlen(s); /* length of string - terminator */
|
|
Packit |
f574b8 |
copy = (char *) s_malloc((size_t) (sizeof(char) * (len + 1)));
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
StrNCpy(copy, s, len + 1);
|
|
Packit |
f574b8 |
return (copy);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *fs_strncat(char *dst, char *src, size_t maxToAdd, size_t maxTotal)
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* like strncat, except the fourth argument limits the maximum total
|
|
Packit |
f574b8 |
length of the resulting string
|
|
Packit |
f574b8 |
*/
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
size_t dstSize = strlen(dst);
|
|
Packit |
f574b8 |
size_t srcSize = strlen(src);
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
if (dstSize + srcSize < maxTotal) /* use regular old strncat */
|
|
Packit |
f574b8 |
return (StrNCat(dst, src, maxToAdd));
|
|
Packit |
f574b8 |
else {
|
|
Packit |
f574b8 |
size_t truncateTo = maxTotal - dstSize - 1;
|
|
Packit |
f574b8 |
char saveChar = src[truncateTo];
|
|
Packit |
f574b8 |
char *result = NULL;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
src[truncateTo] = '\0';
|
|
Packit |
f574b8 |
result = StrNCat(dst, src, maxToAdd);
|
|
Packit |
f574b8 |
src[truncateTo] = saveChar;
|
|
Packit |
f574b8 |
return (result);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char char_downcase(unsigned long long_ch)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
unsigned char ch = long_ch & 0xFF; /* just want one byte */
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/* when ansi is the way of the world, this can be tolower */
|
|
Packit |
f574b8 |
return (((ch >= 'A') && (ch <= 'Z')) ? (ch + 'a' - 'A') : ch);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
char *string_downcase(char *word)
|
|
Packit |
f574b8 |
{
|
|
Packit |
f574b8 |
long i = 0;
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
while (word[i] != '\0') {
|
|
Packit |
f574b8 |
word[i] = char_downcase((unsigned long) word[i]);
|
|
Packit |
f574b8 |
i++;
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
return (word);
|
|
Packit |
f574b8 |
}
|
|
Packit |
f574b8 |
|
|
Packit |
f574b8 |
/*----------------------------------------------------------------------*/
|
|
Packit |
f574b8 |
#endif /* VMS */
|