1125 lines
29 KiB
C
1125 lines
29 KiB
C
/* WIDE AREA INFORMATION SERVER SOFTWARE:
|
|
Developed by Thinking Machines Corporation and put into the public
|
|
domain with no guarantees or restrictions.
|
|
*/
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
#define _C_Z39_50_
|
|
|
|
#include "zprot.h"
|
|
#include "zutil.h"
|
|
#include "cutil.h"
|
|
#include <string.h>
|
|
|
|
#define RESERVE_SPACE_FOR_HEADER(spaceLeft) \
|
|
*spaceLeft -= HEADER_LEN;
|
|
|
|
#define RELEASE_HEADER_SPACE(spaceLeft) \
|
|
if (*spaceLeft > 0) \
|
|
*spaceLeft += HEADER_LEN;
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
InitAPDU*
|
|
makeInitAPDU(search,
|
|
present,
|
|
deleteIt,
|
|
accessControl,
|
|
resourceControl,
|
|
prefSize,
|
|
maxMsgSize,
|
|
auth,
|
|
id,
|
|
name,
|
|
version,
|
|
refID,
|
|
userInfo)
|
|
boolean search;
|
|
boolean present;
|
|
boolean deleteIt;
|
|
boolean accessControl;
|
|
boolean resourceControl;
|
|
long prefSize;
|
|
long maxMsgSize;
|
|
char* auth;
|
|
char* id;
|
|
char* name;
|
|
char* version;
|
|
any* refID;
|
|
void* userInfo;
|
|
|
|
|
|
{
|
|
InitAPDU* init = (InitAPDU*)s_malloc((size_t)sizeof(InitAPDU));
|
|
|
|
init->PDUType = initAPDU;
|
|
init->willSearch = search;
|
|
init->willPresent = present;
|
|
init->willDelete = deleteIt;
|
|
init->supportAccessControl = accessControl;
|
|
init->supportResourceControl = resourceControl;
|
|
init->PreferredMessageSize = prefSize;
|
|
init->MaximumRecordSize = maxMsgSize;
|
|
init->IDAuthentication = s_strdup(auth);
|
|
init->ImplementationID = s_strdup(id);
|
|
init->ImplementationName = s_strdup(name);
|
|
init->ImplementationVersion = s_strdup(version);
|
|
init->ReferenceID = duplicateAny(refID);
|
|
init->UserInformationField = userInfo;
|
|
|
|
return(init);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void
|
|
freeInitAPDU(init)
|
|
InitAPDU* init;
|
|
|
|
{
|
|
s_free(init->IDAuthentication);
|
|
s_free(init->ImplementationID);
|
|
s_free(init->ImplementationName);
|
|
s_free(init->ImplementationVersion);
|
|
freeAny(init->ReferenceID);
|
|
s_free(init);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
writeInitAPDU(init,buffer,len)
|
|
InitAPDU* init;
|
|
char* buffer; /* Pointer into large malloc-ed buffer!!*/
|
|
long* len;
|
|
|
|
{
|
|
char* buf = buffer + HEADER_LEN;
|
|
long size;
|
|
bit_map* optionsBM = NULL;
|
|
|
|
RESERVE_SPACE_FOR_HEADER(len);
|
|
|
|
buf = writePDUType(init->PDUType,buf,len);
|
|
|
|
buf = writeProtocolVersion(buf,len);
|
|
|
|
optionsBM = makeBitMap((unsigned long)5,init->willSearch,init->willPresent,
|
|
init->willDelete,init->supportAccessControl,
|
|
init->supportResourceControl);
|
|
buf = writeBitMap(optionsBM,DT_Options,buf,len);
|
|
freeBitMap(optionsBM);
|
|
|
|
buf = writeNum(init->PreferredMessageSize,DT_PreferredMessageSize,buf,len);
|
|
buf = writeNum(init->MaximumRecordSize,DT_MaximumRecordSize,buf,len);
|
|
buf = writeString(init->IDAuthentication,DT_IDAuthentication,buf,len);
|
|
buf = writeString(init->ImplementationID,DT_ImplementationID,buf,len);
|
|
buf = writeString(init->ImplementationName,DT_ImplementationName,buf,len);
|
|
buf = writeString(init->ImplementationVersion,DT_ImplementationVersion,buf,len);
|
|
buf = writeAny(init->ReferenceID,DT_ReferenceID,buf,len);
|
|
|
|
|
|
RELEASE_HEADER_SPACE(len);
|
|
size = buf - buffer - HEADER_LEN;
|
|
writeBinaryInteger(size,HEADER_LEN,buffer,len);
|
|
|
|
/* Note the UserInformatioNField wont be included in the size !!H*/
|
|
if (init->UserInformationField != NULL)
|
|
buf = writeInitInfo(init,buf,len); /* Note this is dummied out!!*/
|
|
|
|
return(buf);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
readInitAPDU(init,buffer)
|
|
InitAPDU** init;
|
|
char* buffer;
|
|
{
|
|
char* buf = buffer;
|
|
boolean search,present,delete,accessControl,resourceControl;
|
|
long prefSize,maxMsgSize;
|
|
char *auth,*id,*name,*version;
|
|
long size;
|
|
pdu_type pduType;
|
|
bit_map* versionBM = NULL;
|
|
bit_map* optionsBM = NULL;
|
|
any *refID = NULL;
|
|
void* userInfo = NULL;
|
|
|
|
auth = id = name = version = NULL;
|
|
|
|
|
|
buf = readBinaryInteger(&size,HEADER_LEN,buf);
|
|
buf = readPDUType(&pduType,buf);
|
|
buf = readBitMap(&versionBM,buf);
|
|
buf = readBitMap(&optionsBM,buf);
|
|
buf = readNum(&prefSize,buf);
|
|
buf = readNum(&maxMsgSize,buf);
|
|
|
|
|
|
search = bitAtPos(0L,optionsBM);
|
|
present = bitAtPos(1L,optionsBM);
|
|
delete = bitAtPos(2L,optionsBM);
|
|
accessControl = bitAtPos(3L,optionsBM);
|
|
resourceControl = bitAtPos(4L,optionsBM);
|
|
|
|
|
|
while (buf < (buffer + size + HEADER_LEN))
|
|
{ data_tag tag = peekTag(buf);
|
|
switch (tag)
|
|
{ case DT_IDAuthentication:
|
|
buf = readString(&auth,buf);
|
|
break;
|
|
case DT_ImplementationID:
|
|
buf = readString(&id,buf);
|
|
break;
|
|
case DT_ImplementationName:
|
|
buf = readString(&name,buf);
|
|
break;
|
|
case DT_ImplementationVersion:
|
|
buf = readString(&version,buf);
|
|
break;
|
|
case DT_ReferenceID:
|
|
buf = readAny(&refID,buf);
|
|
break;
|
|
default:
|
|
freeBitMap(versionBM);
|
|
freeBitMap(optionsBM);
|
|
s_free(auth);
|
|
s_free(id);
|
|
s_free(name);
|
|
s_free(version);
|
|
freeAny(refID);
|
|
REPORT_READ_ERROR(buf);
|
|
break;
|
|
}
|
|
}
|
|
|
|
buf = readInitInfo(&userInfo,buf);
|
|
if (buf == NULL)
|
|
{ freeBitMap(versionBM);
|
|
freeBitMap(optionsBM);
|
|
s_free(auth);
|
|
s_free(id);
|
|
s_free(name);
|
|
s_free(version);
|
|
freeAny(refID);
|
|
}
|
|
RETURN_ON_NULL(buf);
|
|
|
|
|
|
*init = makeInitAPDU(search,present,delete,accessControl,resourceControl,
|
|
prefSize,maxMsgSize,auth,id,name,version,refID,userInfo);
|
|
|
|
freeBitMap(versionBM);
|
|
freeBitMap(optionsBM);
|
|
s_free(auth);
|
|
s_free(id);
|
|
s_free(name);
|
|
s_free(version);
|
|
freeAny(refID);
|
|
|
|
return(buf);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
InitResponseAPDU*
|
|
makeInitResponseAPDU(result,
|
|
search,
|
|
present,
|
|
deleteIt,
|
|
accessControl,
|
|
resourceControl,
|
|
prefSize,
|
|
maxMsgSize,
|
|
auth,
|
|
id,
|
|
name,
|
|
version,
|
|
refID,
|
|
userInfo)
|
|
boolean result;
|
|
boolean search;
|
|
boolean present;
|
|
boolean deleteIt;
|
|
boolean accessControl;
|
|
boolean resourceControl;
|
|
long prefSize;
|
|
long maxMsgSize;
|
|
char* auth;
|
|
char* id;
|
|
char* name;
|
|
char* version;
|
|
any* refID;
|
|
void* userInfo;
|
|
|
|
{
|
|
InitResponseAPDU* init = (InitResponseAPDU*)s_malloc((size_t)sizeof(InitResponseAPDU));
|
|
|
|
init->PDUType = initResponseAPDU;
|
|
init->Result = result;
|
|
init->willSearch = search;
|
|
init->willPresent = present;
|
|
init->willDelete = deleteIt;
|
|
init->supportAccessControl = accessControl;
|
|
init->supportResourceControl = resourceControl;
|
|
init->PreferredMessageSize = prefSize;
|
|
init->MaximumRecordSize = maxMsgSize;
|
|
init->IDAuthentication = s_strdup(auth);
|
|
init->ImplementationID = s_strdup(id);
|
|
init->ImplementationName = s_strdup(name);
|
|
init->ImplementationVersion = s_strdup(version);
|
|
init->ReferenceID = duplicateAny(refID);
|
|
init->UserInformationField = userInfo;
|
|
|
|
return(init);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void
|
|
freeInitResponseAPDU(init)
|
|
InitResponseAPDU* init;
|
|
|
|
{
|
|
s_free(init->IDAuthentication);
|
|
s_free(init->ImplementationID);
|
|
s_free(init->ImplementationName);
|
|
s_free(init->ImplementationVersion);
|
|
freeAny(init->ReferenceID);
|
|
s_free(init);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
writeInitResponseAPDU(init,buffer,len)
|
|
InitResponseAPDU* init;
|
|
char* buffer;
|
|
long* len;
|
|
|
|
{
|
|
char* buf = buffer + HEADER_LEN;
|
|
long size;
|
|
bit_map* optionsBM = NULL;
|
|
|
|
RESERVE_SPACE_FOR_HEADER(len);
|
|
|
|
buf = writePDUType(init->PDUType,buf,len);
|
|
buf = writeBoolean(init->Result,buf,len);
|
|
buf = writeProtocolVersion(buf,len);
|
|
|
|
optionsBM = makeBitMap((unsigned long)5,init->willSearch,init->willPresent,
|
|
init->willDelete,init->supportAccessControl,
|
|
init->supportResourceControl);
|
|
buf = writeBitMap(optionsBM,DT_Options,buf,len);
|
|
freeBitMap(optionsBM);
|
|
|
|
buf = writeNum(init->PreferredMessageSize,DT_PreferredMessageSize,buf,len);
|
|
buf = writeNum(init->MaximumRecordSize,DT_MaximumRecordSize,buf,len);
|
|
buf = writeString(init->IDAuthentication,DT_IDAuthentication,buf,len);
|
|
buf = writeString(init->ImplementationID,DT_ImplementationID,buf,len);
|
|
buf = writeString(init->ImplementationName,DT_ImplementationName,buf,len);
|
|
buf = writeString(init->ImplementationVersion,DT_ImplementationVersion,buf,len);
|
|
buf = writeAny(init->ReferenceID,DT_ReferenceID,buf,len);
|
|
|
|
|
|
RELEASE_HEADER_SPACE(len);
|
|
size = buf - buffer - HEADER_LEN;
|
|
writeBinaryInteger(size,HEADER_LEN,buffer,len);
|
|
|
|
if (init->UserInformationField != NULL)
|
|
buf = writeInitResponseInfo(init,buf,len);
|
|
|
|
return(buf);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
readInitResponseAPDU(init,buffer)
|
|
InitResponseAPDU** init;
|
|
char* buffer;
|
|
{
|
|
char* buf = buffer;
|
|
boolean search,present,delete,accessControl,resourceControl;
|
|
long prefSize,maxMsgSize;
|
|
char *auth,*id,*name,*version;
|
|
long size;
|
|
pdu_type pduType;
|
|
bit_map* versionBM = NULL;
|
|
bit_map* optionsBM = NULL;
|
|
boolean result;
|
|
any *refID = NULL;
|
|
void* userInfo = NULL;
|
|
|
|
auth = id = name = version = NULL;
|
|
refID = NULL;
|
|
|
|
|
|
buf = readBinaryInteger(&size,HEADER_LEN,buf);
|
|
buf = readPDUType(&pduType,buf);
|
|
buf = readBoolean(&result,buf);
|
|
buf = readBitMap(&versionBM,buf);
|
|
buf = readBitMap(&optionsBM,buf);
|
|
buf = readNum(&prefSize,buf);
|
|
buf = readNum(&maxMsgSize,buf);
|
|
|
|
|
|
search = bitAtPos(0L,optionsBM);
|
|
present = bitAtPos(1L,optionsBM);
|
|
delete = bitAtPos(2L,optionsBM);
|
|
accessControl = bitAtPos(3L,optionsBM);
|
|
resourceControl = bitAtPos(4L,optionsBM);
|
|
|
|
|
|
while (buf < (buffer + size + HEADER_LEN))
|
|
{ data_tag tag = peekTag(buf);
|
|
switch (tag)
|
|
{ case DT_IDAuthentication:
|
|
buf = readString(&auth,buf);
|
|
break;
|
|
case DT_ImplementationID:
|
|
buf = readString(&id,buf);
|
|
break;
|
|
case DT_ImplementationName:
|
|
buf = readString(&name,buf);
|
|
break;
|
|
case DT_ImplementationVersion:
|
|
buf = readString(&version,buf);
|
|
break;
|
|
case DT_ReferenceID:
|
|
buf = readAny(&refID,buf);
|
|
break;
|
|
default:
|
|
freeBitMap(versionBM);
|
|
freeBitMap(optionsBM);
|
|
s_free(auth);
|
|
s_free(id);
|
|
s_free(name);
|
|
s_free(version);
|
|
freeAny(refID);
|
|
REPORT_READ_ERROR(buf);
|
|
break;
|
|
}
|
|
}
|
|
|
|
buf = readInitResponseInfo(&userInfo,buf);
|
|
if (buf == NULL)
|
|
{ freeBitMap(versionBM);
|
|
freeBitMap(optionsBM);
|
|
s_free(auth);
|
|
s_free(id);
|
|
s_free(name);
|
|
s_free(version);
|
|
freeAny(refID);
|
|
}
|
|
RETURN_ON_NULL(buf);
|
|
|
|
|
|
*init = makeInitResponseAPDU(result,
|
|
search,present,delete,accessControl,resourceControl,
|
|
prefSize,maxMsgSize,auth,id,name,version,refID,userInfo);
|
|
|
|
freeBitMap(versionBM);
|
|
freeBitMap(optionsBM);
|
|
s_free(auth);
|
|
s_free(id);
|
|
s_free(name);
|
|
s_free(version);
|
|
freeAny(refID);
|
|
|
|
return(buf);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
InitResponseAPDU*
|
|
replyToInitAPDU(init,result,userInfo)
|
|
InitAPDU* init;
|
|
boolean result;
|
|
void* userInfo;
|
|
|
|
{
|
|
InitResponseAPDU* initResp;
|
|
initResp = makeInitResponseAPDU(result,
|
|
init->willSearch,init->willPresent,init->willDelete,
|
|
init->supportAccessControl,init->supportResourceControl,
|
|
init->PreferredMessageSize,init->MaximumRecordSize,
|
|
init->IDAuthentication,defaultImplementationID(),defaultImplementationName(),
|
|
defaultImplementationVersion(),
|
|
init->ReferenceID,userInfo);
|
|
return(initResp);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
SearchAPDU*
|
|
makeSearchAPDU(small,
|
|
large,
|
|
medium,
|
|
replace,
|
|
name,
|
|
databases,
|
|
type,
|
|
elements,
|
|
refID,
|
|
queryInfo)
|
|
long small;
|
|
long large;
|
|
long medium;
|
|
boolean replace;
|
|
char* name;
|
|
char** databases;
|
|
char* type;
|
|
char** elements;
|
|
any* refID;
|
|
void* queryInfo;
|
|
{
|
|
char* ptr = NULL;
|
|
long i;
|
|
SearchAPDU* query = (SearchAPDU*)s_malloc((size_t)sizeof(SearchAPDU));
|
|
query->PDUType = searchAPDU;
|
|
query->SmallSetUpperBound = small;
|
|
query->LargeSetLowerBound = large;
|
|
query->MediumSetPresentNumber = medium;
|
|
query->ReplaceIndicator = replace;
|
|
query->ResultSetName = s_strdup(name);
|
|
query->DatabaseNames = NULL;
|
|
if (databases != NULL)
|
|
{ for (i = 0, ptr = databases[i]; ptr != NULL; ptr = databases[++i])
|
|
{ if (query->DatabaseNames == NULL)
|
|
query->DatabaseNames = (char**)s_malloc((size_t)(sizeof(char*) * 2));
|
|
else
|
|
query->DatabaseNames = (char**)s_realloc((char*)query->DatabaseNames,
|
|
(size_t)(sizeof(char*) * (i + 2)));
|
|
query->DatabaseNames[i] = s_strdup(ptr);
|
|
query->DatabaseNames[i+1] = NULL;
|
|
}
|
|
}
|
|
query->QueryType = s_strdup(type);
|
|
query->ElementSetNames = NULL;
|
|
if (elements != NULL)
|
|
{ for (i = 0, ptr = elements[i]; ptr != NULL; ptr = elements[++i])
|
|
{ if (query->ElementSetNames == NULL)
|
|
query->ElementSetNames = (char**)s_malloc((size_t)(sizeof(char*) * 2));
|
|
else
|
|
query->ElementSetNames = (char**)s_realloc((char*)query->ElementSetNames,
|
|
(size_t)(sizeof(char*) * (i + 2)));
|
|
query->ElementSetNames[i] = s_strdup(ptr);
|
|
query->ElementSetNames[i+1] = NULL;
|
|
}
|
|
}
|
|
query->ReferenceID = duplicateAny(refID);
|
|
query->Query = queryInfo;
|
|
return(query);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void
|
|
freeSearchAPDU(query)
|
|
SearchAPDU* query;
|
|
{
|
|
s_free(query->ResultSetName);
|
|
s_free(query->QueryType);
|
|
doList((void**)query->DatabaseNames,fs_free);
|
|
s_free(query->DatabaseNames);
|
|
doList((void**)query->ElementSetNames,fs_free);
|
|
s_free(query->ElementSetNames);
|
|
freeAny(query->ReferenceID);
|
|
s_free(query);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
#define DB_DELIMITER "\037"
|
|
#define ES_DELIMITER_1 "\037"
|
|
#define ES_DELIMITER_2 "\036"
|
|
|
|
char*
|
|
writeSearchAPDU(query,buffer,len)
|
|
SearchAPDU* query;
|
|
char* buffer;
|
|
long* len;
|
|
{
|
|
char* buf = buffer + HEADER_LEN;
|
|
long size,i;
|
|
char* ptr = NULL;
|
|
char* scratch = NULL;
|
|
|
|
RESERVE_SPACE_FOR_HEADER(len);
|
|
|
|
buf = writePDUType(query->PDUType,buf,len);
|
|
buf = writeBinaryInteger(query->SmallSetUpperBound,(size_t)3,buf,len);
|
|
buf = writeBinaryInteger(query->LargeSetLowerBound,(size_t)3,buf,len);
|
|
buf = writeBinaryInteger(query->MediumSetPresentNumber,(size_t)3,buf,len);
|
|
buf = writeBoolean(query->ReplaceIndicator,buf,len);
|
|
buf = writeString(query->ResultSetName,DT_ResultSetName,buf,len);
|
|
|
|
if (query->DatabaseNames != NULL)
|
|
{ for (i = 0,scratch = NULL, ptr = query->DatabaseNames[i]; ptr != NULL; ptr = query->DatabaseNames[++i])
|
|
{ if (scratch == NULL)
|
|
scratch = s_strdup(ptr);
|
|
else
|
|
{ size_t newScratchSize = (size_t)(strlen(scratch) + strlen(ptr) + 3);
|
|
scratch = (char*)s_realloc(scratch,newScratchSize);
|
|
s_strncat(scratch,DB_DELIMITER,2L,newScratchSize);
|
|
s_strncat(scratch,ptr,strlen(ptr) + 1,newScratchSize);
|
|
}
|
|
}
|
|
buf = writeString(scratch,DT_DatabaseNames,buf,len);
|
|
s_free(scratch);
|
|
}
|
|
buf = writeString(query->QueryType,DT_QueryType,buf,len);
|
|
|
|
if (query->ElementSetNames != NULL)
|
|
{ for (i = 0,scratch = NULL, ptr = query->ElementSetNames[i]; ptr != NULL; ptr = query->ElementSetNames[++i])
|
|
{ if (scratch == NULL)
|
|
{ if (query->ElementSetNames[i+1] == NULL)
|
|
{ scratch = (char*)s_malloc((size_t)strlen(ptr) + 3);
|
|
strncpy(scratch,ES_DELIMITER_1,2);
|
|
s_strncat(scratch,ptr,strlen(ptr) + 1,strlen(ptr) + 2);
|
|
}
|
|
else
|
|
{ size_t newScratchSize = (size_t)(strlen(ptr) + strlen(query->ElementSetNames[i + 1]) + 3);
|
|
scratch = s_strdup(ptr);
|
|
ptr = query->ElementSetNames[++i];
|
|
scratch = (char*)s_realloc(scratch,newScratchSize);
|
|
s_strncat(scratch,ES_DELIMITER_1,2L,newScratchSize);
|
|
s_strncat(scratch,ptr,strlen(ptr) + 1,newScratchSize);
|
|
}
|
|
}
|
|
else
|
|
{ char* esPtr = query->ElementSetNames[++i];
|
|
size_t newScratchSize = (size_t)(strlen(scratch) + strlen(ptr) + strlen(esPtr) + 3);
|
|
scratch = (char*)s_realloc(scratch,newScratchSize);
|
|
s_strncat(scratch,ES_DELIMITER_2,2L,newScratchSize);
|
|
s_strncat(scratch,ptr,strlen(ptr) + 1,newScratchSize);
|
|
s_strncat(scratch,ES_DELIMITER_1,2L,newScratchSize);
|
|
s_strncat(scratch,esPtr,strlen(esPtr) + 1,newScratchSize);
|
|
}
|
|
}
|
|
buf = writeString(scratch,DT_ElementSetNames,buf,len);
|
|
s_free(scratch);
|
|
}
|
|
buf = writeAny(query->ReferenceID,DT_ReferenceID,buf,len);
|
|
|
|
|
|
RELEASE_HEADER_SPACE(len);
|
|
size = buf - buffer - HEADER_LEN;
|
|
writeBinaryInteger(size,HEADER_LEN,buffer,len);
|
|
|
|
if (query->Query != NULL)
|
|
buf = writeSearchInfo(query,buf,len);
|
|
|
|
return(buf);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
#if !defined(IN_RMG) && !defined(PFS_THREADS)
|
|
/* Note - uses strtok */
|
|
char*
|
|
readSearchAPDU(query,buffer)
|
|
SearchAPDU** query;
|
|
char* buffer;
|
|
{
|
|
char* buf = buffer;
|
|
long size;
|
|
pdu_type pduType;
|
|
long small,large,medium,numItems;
|
|
boolean replace;
|
|
char *name,*databaseNames,*type,*elements;
|
|
char **dbList,**elemList;
|
|
any *refID;
|
|
void* userInfo = NULL;
|
|
|
|
name = databaseNames = type = elements = NULL;
|
|
dbList = elemList = NULL;
|
|
refID = NULL;
|
|
|
|
|
|
buf = readBinaryInteger(&size,HEADER_LEN,buf);
|
|
buf = readPDUType(&pduType,buf);
|
|
buf = readBinaryInteger(&small,(size_t)3,buf);
|
|
buf = readBinaryInteger(&large,(size_t)3,buf);
|
|
buf = readBinaryInteger(&medium,(size_t)3,buf);
|
|
buf = readBoolean(&replace,buf);
|
|
|
|
|
|
while (buf < (buffer + size + HEADER_LEN))
|
|
{ data_tag tag = peekTag(buf);
|
|
switch (tag)
|
|
{ case DT_ResultSetName:
|
|
buf = readString(&name,buf);
|
|
break;
|
|
case DT_DatabaseNames:
|
|
{
|
|
char *tok;
|
|
buf = readString(&databaseNames,buf);
|
|
assert(P_IS_THIS_THREAD_MASTER());
|
|
tok = strtok(databaseNames,DB_DELIMITER);
|
|
numItems = 0;
|
|
while (tok != NULL)
|
|
{ if (dbList == NULL)
|
|
dbList = (char**)s_malloc((size_t)(sizeof(char*) * 2));
|
|
else
|
|
dbList = (char**)s_realloc((char*)dbList,(size_t)(sizeof(char*) * (numItems+2)));
|
|
dbList[numItems++] = s_strdup(tok);
|
|
dbList[numItems] = NULL;
|
|
tok = strtok(NULL,DB_DELIMITER);
|
|
}
|
|
}
|
|
break;
|
|
case DT_QueryType:
|
|
buf = readString(&type,buf);
|
|
break;
|
|
case DT_ElementSetNames:
|
|
{
|
|
char *tok;
|
|
buf = readString(&elements,buf);
|
|
if (elements[0] == ES_DELIMITER_1[0])
|
|
{ elemList = (char**)s_malloc((size_t)(sizeof(char*) * 2));
|
|
elemList[0] = s_strdup(elements);
|
|
elemList[1] = NULL;
|
|
}
|
|
else
|
|
{ char* esTok = NULL;
|
|
assert(P_IS_THIS_THREAD_MASTER()); /* strtok thread unsafe */
|
|
tok = strtok(elements,ES_DELIMITER_1);
|
|
esTok = strtok(NULL,ES_DELIMITER_2);
|
|
numItems = 0;
|
|
while (tok != NULL)
|
|
{ if (elemList == NULL)
|
|
elemList = (char**)s_malloc((size_t)(sizeof(char*) * 3));
|
|
else
|
|
elemList = (char**)s_realloc((char*)elemList,(size_t)(sizeof(char*) * (numItems * 2 + 1)));
|
|
elemList[numItems++] = s_strdup(tok);
|
|
elemList[numItems++] = s_strdup(esTok);
|
|
elemList[numItems] = NULL;
|
|
tok = strtok(NULL,ES_DELIMITER_1);
|
|
esTok = strtok(NULL,ES_DELIMITER_2);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case DT_ReferenceID:
|
|
buf = readAny(&refID,buf);
|
|
break;
|
|
default:
|
|
s_free(name);
|
|
s_free(type);
|
|
s_free(databaseNames);
|
|
doList((void**)dbList,fs_free);
|
|
s_free(dbList);
|
|
s_free(elements);
|
|
doList((void**)elemList,fs_free);
|
|
s_free(elemList);
|
|
freeAny(refID);
|
|
REPORT_READ_ERROR(buf);
|
|
break;
|
|
}
|
|
}
|
|
|
|
buf = readSearchInfo(&userInfo,buf);
|
|
if (buf == NULL)
|
|
{ s_free(name);
|
|
s_free(type);
|
|
s_free(databaseNames);
|
|
doList((void**)dbList,fs_free);
|
|
s_free(dbList);
|
|
s_free(elements);
|
|
doList((void**)elemList,fs_free);
|
|
s_free(elemList);
|
|
freeAny(refID);
|
|
}
|
|
RETURN_ON_NULL(buf);
|
|
|
|
|
|
*query = makeSearchAPDU(small,large,medium,replace,name,dbList,type,elemList,refID,userInfo);
|
|
|
|
s_free(name);
|
|
s_free(type);
|
|
s_free(databaseNames);
|
|
doList((void**)dbList,fs_free);
|
|
s_free(dbList);
|
|
s_free(elements);
|
|
doList((void**)elemList,fs_free);
|
|
s_free(elemList);
|
|
freeAny(refID);
|
|
|
|
return(buf);
|
|
}
|
|
|
|
#endif /*!IN_RMG && !PFS_THREADS*/
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
SearchResponseAPDU*
|
|
makeSearchResponseAPDU(result,count,recordsReturned,nextPos,resultStatus,
|
|
presentStatus,refID,records)
|
|
long result;
|
|
long count;
|
|
long recordsReturned;
|
|
long nextPos;
|
|
long resultStatus;
|
|
long presentStatus;
|
|
any* refID;
|
|
void* records;
|
|
{
|
|
SearchResponseAPDU* query = (SearchResponseAPDU*)s_malloc((size_t)sizeof(SearchResponseAPDU));
|
|
query->PDUType = searchResponseAPDU;
|
|
query->SearchStatus = result;
|
|
query->ResultCount = count;
|
|
query->NumberOfRecordsReturned = recordsReturned;
|
|
query->NextResultSetPosition = nextPos;
|
|
query->ResultSetStatus = resultStatus;
|
|
query->PresentStatus = presentStatus;
|
|
query->ReferenceID = duplicateAny(refID);
|
|
query->DatabaseDiagnosticRecords = records;
|
|
return(query);
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void
|
|
freeSearchResponseAPDU(queryResponse)
|
|
SearchResponseAPDU* queryResponse;
|
|
{
|
|
freeAny(queryResponse->ReferenceID);
|
|
s_free(queryResponse);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
#if !defined(IN_RMG) && !defined(PFS_THREADS)
|
|
|
|
char*
|
|
writeSearchResponseAPDU(queryResponse,buffer,len)
|
|
SearchResponseAPDU* queryResponse;
|
|
char* buffer;
|
|
long* len;
|
|
{
|
|
char* buf = buffer + HEADER_LEN;
|
|
long size;
|
|
|
|
RESERVE_SPACE_FOR_HEADER(len);
|
|
|
|
buf = writePDUType(queryResponse->PDUType,buf,len);
|
|
buf = writeBinaryInteger(queryResponse->SearchStatus,(size_t)1,buf,len);
|
|
buf = writeBinaryInteger(queryResponse->ResultCount,(size_t)3,buf,len);
|
|
buf = writeBinaryInteger(queryResponse->NumberOfRecordsReturned,(size_t)3,buf,len);
|
|
buf = writeBinaryInteger(queryResponse->NextResultSetPosition,(size_t)3,buf,len);
|
|
buf = writeNum(queryResponse->ResultSetStatus,DT_ResultSetStatus,buf,len);
|
|
buf = writeNum(queryResponse->PresentStatus,DT_PresentStatus,buf,len);
|
|
buf = writeAny(queryResponse->ReferenceID,DT_ReferenceID,buf,len);
|
|
|
|
|
|
RELEASE_HEADER_SPACE(len);
|
|
size = buf - buffer - HEADER_LEN;
|
|
writeBinaryInteger(size,HEADER_LEN,buffer,len);
|
|
|
|
if (queryResponse->DatabaseDiagnosticRecords != NULL)
|
|
buf = writeSearchResponseInfo(queryResponse,buf,len);
|
|
|
|
return(buf);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
#endif /*!IN_RMG && !PFS_THREADS*/
|
|
char*
|
|
readSearchResponseAPDU(queryResponse,buffer)
|
|
SearchResponseAPDU** queryResponse;
|
|
char* buffer;
|
|
{
|
|
char* buf = buffer;
|
|
long size;
|
|
pdu_type pduType;
|
|
long result,count,recordsReturned,nextPos;
|
|
long resultStatus,presentStatus;
|
|
any *refID = NULL;
|
|
void* userInfo = NULL;
|
|
|
|
|
|
buf = readBinaryInteger(&size,HEADER_LEN,buf);
|
|
buf = readPDUType(&pduType,buf);
|
|
buf = readBinaryInteger(&result,(size_t)1,buf);
|
|
buf = readBinaryInteger(&count,(size_t)3,buf);
|
|
buf = readBinaryInteger(&recordsReturned,(size_t)3,buf);
|
|
buf = readBinaryInteger(&nextPos,(size_t)3,buf);
|
|
|
|
resultStatus = presentStatus = UNUSED;
|
|
refID = NULL;
|
|
|
|
|
|
while (buf < (buffer + size + HEADER_LEN))
|
|
{ data_tag tag = peekTag(buf);
|
|
switch (tag)
|
|
{ case DT_ResultSetStatus:
|
|
buf = readNum(&resultStatus,buf);
|
|
break;
|
|
case DT_PresentStatus:
|
|
buf = readNum(&presentStatus,buf);
|
|
break;
|
|
case DT_ReferenceID:
|
|
buf = readAny(&refID,buf);
|
|
break;
|
|
default:
|
|
freeAny(refID);
|
|
REPORT_READ_ERROR(buf);
|
|
break;
|
|
}
|
|
}
|
|
|
|
buf = readSearchResponseInfo(&userInfo,buf);
|
|
if (buf == NULL)
|
|
freeAny(refID);
|
|
RETURN_ON_NULL(buf);
|
|
|
|
|
|
*queryResponse = makeSearchResponseAPDU(result,count,recordsReturned,nextPos,
|
|
(long)resultStatus,(long)presentStatus,refID,userInfo);
|
|
|
|
freeAny(refID);
|
|
|
|
return(buf);
|
|
}
|
|
#if !defined(IN_RMG) && !defined(PFS_THREADS)
|
|
|
|
#ifdef NOTUSED
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
|
|
PresentAPDU*
|
|
makePresentAPDU(recsReq,startPos,resultID,refID,info)
|
|
long recsReq;
|
|
long startPos;
|
|
char* resultID;
|
|
any* refID;
|
|
void* info;
|
|
{
|
|
PresentAPDU* present = (PresentAPDU*)s_malloc((size_t)sizeof(PresentAPDU));
|
|
present->PDUType = presentAPDU;
|
|
present->NumberOfRecordsRequested = recsReq;
|
|
present->ResultSetStartPosition = startPos;
|
|
present->ResultSetID = s_strdup(resultID);
|
|
present->ElementSetNames = NULL;
|
|
present->ReferenceID = duplicateAny(refID);
|
|
present->PresentInfo = info;
|
|
return(present);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void
|
|
freePresentAPDU(present)
|
|
PresentAPDU* present;
|
|
{
|
|
|
|
s_free(present->ResultSetID);
|
|
freeAny(present->ReferenceID);
|
|
s_free(present);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
writePresentAPDU(present,buffer,len)
|
|
PresentAPDU* present;
|
|
char* buffer;
|
|
long* len;
|
|
{
|
|
char* buf = buffer + HEADER_LEN;
|
|
long size;
|
|
|
|
RESERVE_SPACE_FOR_HEADER(len);
|
|
|
|
buf = writePDUType(present->PDUType,buf,len);
|
|
buf = writeBinaryInteger(present->NumberOfRecordsRequested,(size_t)3,buf,len);
|
|
buf = writeBinaryInteger(present->ResultSetStartPosition,(size_t)3,buf,len);
|
|
buf = writeString(present->ResultSetID,DT_ResultSetID,buf,len);
|
|
|
|
buf = writeAny(present->ReferenceID,DT_ReferenceID,buf,len);
|
|
|
|
|
|
RELEASE_HEADER_SPACE(len);
|
|
size = buf - buffer - HEADER_LEN;
|
|
writeBinaryInteger(size,HEADER_LEN,buffer,len);
|
|
|
|
if (present->PresentInfo != NULL)
|
|
buf = writePresentInfo(present,buf,len);
|
|
|
|
return(buf);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
readPresentAPDU(present,buffer)
|
|
PresentAPDU** present;
|
|
char* buffer;
|
|
{
|
|
char* buf = buffer;
|
|
long size;
|
|
pdu_type pduType;
|
|
long recsReq,startPos;
|
|
char* resultID = NULL;
|
|
any *refID = NULL;
|
|
void* userInfo = NULL;
|
|
|
|
|
|
buf = readBinaryInteger(&size,HEADER_LEN,buf);
|
|
buf = readPDUType(&pduType,buf);
|
|
buf = readBinaryInteger(&recsReq,(size_t)3,buf);
|
|
buf = readBinaryInteger(&startPos,(size_t)3,buf);
|
|
buf = readString(&resultID,buf);
|
|
|
|
|
|
while (buf < (buffer + size + HEADER_LEN))
|
|
{ data_tag tag = peekTag(buf);
|
|
switch (tag)
|
|
{ case DT_ReferenceID:
|
|
buf = readAny(&refID,buf);
|
|
break;
|
|
default:
|
|
s_free(resultID);
|
|
freeAny(refID);
|
|
REPORT_READ_ERROR(buf);
|
|
break;
|
|
}
|
|
}
|
|
|
|
buf = readPresentInfo(&userInfo,buf);
|
|
if (buf == NULL)
|
|
{ s_free(resultID);
|
|
freeAny(refID);
|
|
}
|
|
RETURN_ON_NULL(buf);
|
|
|
|
|
|
*present = makePresentAPDU(recsReq,startPos,resultID,refID,userInfo);
|
|
|
|
s_free(resultID);
|
|
freeAny(refID);
|
|
|
|
return(buf);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
|
|
PresentResponseAPDU*
|
|
makePresentResponseAPDU(status,recsRet,nextPos,refID,records)
|
|
boolean status;
|
|
long recsRet;
|
|
long nextPos;
|
|
any* refID;
|
|
void* records;
|
|
{
|
|
PresentResponseAPDU* present = (PresentResponseAPDU*)s_malloc((size_t)sizeof(PresentResponseAPDU));
|
|
present->PDUType = presentResponseAPDU;
|
|
present->PresentStatus = status;
|
|
present->NumberOfRecordsReturned = recsRet;
|
|
present->NextResultSetPosition = nextPos;
|
|
present->ReferenceID = duplicateAny(refID);
|
|
present->DatabaseDiagnosticRecords = records;
|
|
return(present);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void
|
|
freePresentResponseAPDU(present)
|
|
PresentResponseAPDU* present;
|
|
{
|
|
freeAny(present->ReferenceID);
|
|
s_free(present);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
writePresentResponseAPDU(present,buffer,len)
|
|
PresentResponseAPDU* present;
|
|
char* buffer;
|
|
long* len;
|
|
{
|
|
char* buf = buffer + HEADER_LEN;
|
|
long size;
|
|
|
|
RESERVE_SPACE_FOR_HEADER(len);
|
|
|
|
buf = writePDUType(present->PDUType,buf,len);
|
|
buf = writeBoolean(present->PresentStatus,buf,len);
|
|
buf = writeBinaryInteger(present->NumberOfRecordsReturned,(size_t)3,buf,len);
|
|
buf = writeBinaryInteger(present->NextResultSetPosition,(size_t)3,buf,len);
|
|
buf = writeAny(present->ReferenceID,DT_ReferenceID,buf,len);
|
|
|
|
|
|
RELEASE_HEADER_SPACE(len);
|
|
size = buf - buffer - HEADER_LEN;
|
|
writeBinaryInteger(size,HEADER_LEN,buffer,len);
|
|
|
|
if (present->DatabaseDiagnosticRecords != NULL)
|
|
buf = writePresentResponseInfo(present,buf,len);
|
|
|
|
return(buf);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
readPresentResponseAPDU(present,buffer)
|
|
PresentResponseAPDU** present;
|
|
char* buffer;
|
|
{
|
|
char* buf = buffer;
|
|
long size;
|
|
pdu_type pduType;
|
|
boolean status;
|
|
long recsRet,nextPos;
|
|
any *refID = NULL;
|
|
void* userInfo = NULL;
|
|
|
|
|
|
buf = readBinaryInteger(&size,HEADER_LEN,buf);
|
|
buf = readPDUType(&pduType,buf);
|
|
buf = readBoolean(&status,buf);
|
|
buf = readBinaryInteger(&recsRet,(size_t)3,buf);
|
|
buf = readBinaryInteger(&nextPos,(size_t)3,buf);
|
|
|
|
|
|
while (buf < (buffer + size + HEADER_LEN))
|
|
{ data_tag tag = peekTag(buf);
|
|
switch (tag)
|
|
{ case DT_ReferenceID:
|
|
buf = readAny(&refID,buf);
|
|
break;
|
|
default:
|
|
freeAny(refID);
|
|
REPORT_READ_ERROR(buf);
|
|
break;
|
|
}
|
|
}
|
|
|
|
buf = readPresentResponseInfo(&userInfo,buf);
|
|
if (buf == NULL)
|
|
freeAny(refID);
|
|
RETURN_ON_NULL(buf);
|
|
|
|
|
|
*present = makePresentResponseAPDU(status,recsRet,nextPos,refID,userInfo);
|
|
|
|
freeAny(refID);
|
|
|
|
return(buf);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
|
|
#endif /*NOTUSED*/
|
|
#endif /*!IN_RMG && !PFS_THREADS*/
|