home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / EXTRAS / WINWAIS / IR / ZPROT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-07  |  34.0 KB  |  1,141 lines

  1. /* WIDE AREA INFORMATION SERVER SOFTWARE:`
  2.    No guarantees or restrictions.  See the readme file for the full standard
  3.    disclaimer.
  4.  
  5.    3.26.90      Harry Morris, morris@think.com
  6.    3.30.90  Harry Morris - Changed any->bits to any->bytes
  7.    4.11.90  HWM - generalized conditional includes (see c-dialect.h)
  8. */
  9.  
  10. #define _C_Z39_50_
  11.  
  12. #include "cdialect.h"
  13. #include "zprot.h"
  14.  
  15. #include "zutil.h"
  16. #include "cutil.h"
  17. #include <string.h>
  18.  
  19. #define RESERVE_SPACE_FOR_HEADER(spaceLeft)             \
  20.         *spaceLeft -= HEADER_LEN;
  21.  
  22. #define RELEASE_HEADER_SPACE(spaceLeft)                 \
  23.         if (*spaceLeft > 0)                                                     \
  24.           *spaceLeft += HEADER_LEN;
  25.  
  26. /*----------------------------------------------------------------------*/
  27.  
  28. InitAPDU*
  29. makeInitAPDU(search,
  30.              present,
  31.              deleteIt,
  32.              accessControl,
  33.              resourceControl,
  34.              prefSize,
  35.              maxMsgSize,
  36.              auth,
  37.              id,
  38.              name,
  39.              version,
  40.              refID,
  41.              userInfo)
  42. boolean search;
  43. boolean present;
  44. boolean deleteIt;
  45. boolean accessControl;
  46. boolean resourceControl;
  47. long prefSize;
  48. long maxMsgSize;
  49. char* auth;
  50. char* id;
  51. char* name;
  52. char* version;
  53. any* refID;
  54. void* userInfo;
  55.  
  56.  
  57. /* build an init APDU with user specified information */
  58. {
  59.  
  60.   InitAPDU* init = (InitAPDU*)s_malloc((long)sizeof(InitAPDU));
  61.   init->PDUType = initAPDU;
  62.   init->willSearch = search;
  63.   init->willPresent = present;
  64.   init->willDelete = deleteIt;
  65.   init->supportAccessControl = accessControl;
  66.   init->supportResourceControl = resourceControl;
  67.   init->PreferredMessageSize = prefSize;
  68.   init->MaximumRecordSize = maxMsgSize;
  69.   init->IDAuthentication = s_strdup(auth);
  70.   init->ImplementationID = s_strdup(id);
  71.   init->ImplementationName = s_strdup(name);
  72.   init->ImplementationVersion = s_strdup(version);
  73.   init->ReferenceID = duplicateAny(refID);
  74.   init->UserInformationField = userInfo; /* not copied */
  75.  
  76.   return(init);
  77. }
  78.  
  79. /*----------------------------------------------------------------------*/
  80.  
  81. void
  82. freeInitAPDU(init)
  83. InitAPDU* init;
  84. /* free an initAPDU */
  85. {
  86.   s_free(init->IDAuthentication);
  87.   s_free(init->ImplementationID);
  88.   s_free(init->ImplementationName);
  89.   s_free(init->ImplementationVersion);
  90.   freeAny(init->ReferenceID);
  91.   s_free(init);
  92. }
  93.  
  94. /*----------------------------------------------------------------------*/
  95.  
  96. char*
  97. writeInitAPDU(init,buffer,len)
  98. InitAPDU* init;
  99. char* buffer;
  100. long* len;
  101. /* write the init to a buffer, adding system information */
  102. {
  103.   char* buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
  104.   long size;
  105.   bit_map* optionsBM = NULL;
  106.  
  107.   RESERVE_SPACE_FOR_HEADER(len);
  108.  
  109.   buf = writePDUType(init->PDUType,buf,len);
  110.  
  111.   buf = writeProtocolVersion(buf,len);
  112.  
  113.   optionsBM = makeBitMap((unsigned long)5,init->willSearch,init->willPresent,
  114.                          init->willDelete,init->supportAccessControl,
  115.                          init->supportResourceControl);
  116.   buf = writeBitMap(optionsBM,DT_Options,buf,len);
  117.   freeBitMap(optionsBM);
  118.  
  119.   buf = writeNum(init->PreferredMessageSize,DT_PreferredMessageSize,buf,len);
  120.   buf = writeNum(init->MaximumRecordSize,DT_MaximumRecordSize,buf,len);
  121.   buf = writeString(init->IDAuthentication,DT_IDAuthentication,buf,len);
  122.   buf = writeString(init->ImplementationID,DT_ImplementationID,buf,len);
  123.   buf = writeString(init->ImplementationName,DT_ImplementationName,buf,len);
  124.   buf = writeString(init->ImplementationVersion,DT_ImplementationVersion,buf,len);
  125.   buf = writeAny(init->ReferenceID,DT_ReferenceID,buf,len);
  126.  
  127.   /* go back and write the header-length-indicator */
  128.   RELEASE_HEADER_SPACE(len);
  129.   size =(long)( buf - buffer);
  130.  
  131.    size-=HEADER_LEN;
  132.   writeBinaryInteger(size,(long)HEADER_LEN,buffer,len);
  133.  
  134.   if (init->UserInformationField != NULL)
  135.     buf = writeInitInfo(init,buf,len);
  136.  
  137.   return(buf);
  138. }
  139.  
  140. /*----------------------------------------------------------------------*/
  141.  
  142. char*
  143. readInitAPDU(init,buffer)
  144. InitAPDU** init;
  145. char* buffer;
  146. {
  147.   char* buf = buffer;
  148.   boolean search,present,delete,accessControl,resourceControl;
  149.   long prefSize,maxMsgSize;
  150.   char *auth,*id,*name,*version;
  151.   long size;
  152.   pdu_type pduType;
  153.   bit_map* versionBM = NULL;
  154.   bit_map* optionsBM = NULL;
  155.   any *refID = NULL;
  156.   void* userInfo = NULL;
  157.  
  158.   auth = id = name = version = NULL;
  159.  
  160.   /* read required part */
  161.   buf = readBinaryInteger(&size,HEADER_LEN,buf);
  162.   buf = readPDUType(&pduType,buf);
  163.   buf = readBitMap(&versionBM,buf);
  164.   buf = readBitMap(&optionsBM,buf);
  165.   buf = readNum(&prefSize,buf);
  166.   buf = readNum(&maxMsgSize,buf);
  167.  
  168.   /* decode optionsBM */
  169.   search = bitAtPos(0L,optionsBM);
  170.   present = bitAtPos(1L,optionsBM);
  171.   delete = bitAtPos(2L,optionsBM);
  172.   accessControl = bitAtPos(3L,optionsBM);
  173.   resourceControl = bitAtPos(4L,optionsBM);
  174.  
  175.   /* read optional part */
  176.   while (buf < (buffer + size + HEADER_LEN))
  177.     { data_tag tag = peekTag(buf);
  178.       switch (tag)
  179.         { case DT_IDAuthentication:
  180.             buf = readString(&auth,buf);
  181.             break;
  182.           case DT_ImplementationID:
  183.             buf = readString(&id,buf);
  184.             break;
  185.           case DT_ImplementationName:
  186.             buf = readString(&name,buf);
  187.             break;
  188.           case DT_ImplementationVersion:
  189.             buf = readString(&version,buf);
  190.             break;
  191.           case DT_ReferenceID:
  192.             buf = readAny(&refID,buf);
  193.             break;
  194.           default:
  195.             freeBitMap(versionBM);
  196.             freeBitMap(optionsBM);
  197.             s_free(auth);
  198.             s_free(id);
  199.             s_free(name);
  200.             s_free(version);
  201.             freeAny(refID);
  202.             REPORT_READ_ERROR(buf);
  203.             break;
  204.           }
  205.     }
  206.  
  207.   buf = readInitInfo(&userInfo,buf);
  208.   if (buf == NULL)
  209.     { freeBitMap(versionBM);
  210.       freeBitMap(optionsBM);
  211.       s_free(auth);
  212.       s_free(id);
  213.       s_free(name);
  214.       s_free(version);
  215.       freeAny(refID);
  216.     }
  217.   RETURN_ON_NULL(buf);
  218.  
  219.   /* construct the basic init object */
  220.   *init = makeInitAPDU(search,present,delete,accessControl,resourceControl,
  221.                        prefSize,maxMsgSize,auth,id,name,version,refID,userInfo);
  222.  
  223.   freeBitMap(versionBM);
  224.   freeBitMap(optionsBM);
  225.   s_free(auth);
  226.   s_free(id);
  227.   s_free(name);
  228.   s_free(version);
  229.   freeAny(refID);
  230.  
  231.   return(buf);
  232. }
  233.  
  234. /*----------------------------------------------------------------------*/
  235.  
  236. InitResponseAPDU*
  237. makeInitResponseAPDU(result,
  238.                      search,
  239.                      present,
  240.                      deleteIt,
  241.                      accessControl,
  242.                      resourceControl,
  243.                      prefSize,
  244.                      maxMsgSize,
  245.                      auth,
  246.                      id,
  247.                      name,
  248.                      version,
  249.                      refID,
  250.                      userInfo)
  251. boolean result;
  252. boolean search;
  253. boolean present;
  254. boolean deleteIt;
  255. boolean accessControl;
  256. boolean resourceControl;
  257. long prefSize;
  258. long maxMsgSize;
  259. char* auth;
  260. char* id;
  261. char* name;
  262. char* version;
  263. any* refID;
  264. void* userInfo;
  265. /* build an initResponse APDU with user specified information */
  266. {
  267.   InitResponseAPDU* init = (InitResponseAPDU*)s_malloc((long)sizeof(InitResponseAPDU));
  268.  
  269.   init->PDUType = initResponseAPDU;
  270.   init->Result = result;
  271.   init->willSearch = search;
  272.   init->willPresent = present;
  273.   init->willDelete = deleteIt;
  274.   init->supportAccessControl = accessControl;
  275.   init->supportResourceControl = resourceControl;
  276.   init->PreferredMessageSize = prefSize;
  277.   init->MaximumRecordSize = maxMsgSize;
  278.   init->IDAuthentication = s_strdup(auth);
  279.   init->ImplementationID = s_strdup(id);
  280.   init->ImplementationName = s_strdup(name);
  281.   init->ImplementationVersion = s_strdup(version);
  282.   init->ReferenceID = duplicateAny(refID);
  283.   init->UserInformationField = userInfo; /* not copied! */
  284.  
  285.   return(init);
  286. }
  287.  
  288. /*----------------------------------------------------------------------*/
  289.  
  290. void
  291. freeInitResponseAPDU(init)
  292. InitResponseAPDU* init;
  293. /* free an initAPDU */
  294. {
  295.   s_free(init->IDAuthentication);
  296.   s_free(init->ImplementationID);
  297.   s_free(init->ImplementationName);
  298.   s_free(init->ImplementationVersion);
  299.   freeAny(init->ReferenceID);
  300.   s_free(init);
  301. }
  302.  
  303. /*----------------------------------------------------------------------*/
  304.  
  305. char*
  306. writeInitResponseAPDU(init,buffer,len)
  307. InitResponseAPDU* init;
  308. char* buffer;
  309. long* len;
  310. /* write the initResponse to a buffer, adding system information */
  311. {
  312.   char* buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
  313.   long size;
  314.   bit_map* optionsBM = NULL;
  315.  
  316.   RESERVE_SPACE_FOR_HEADER(len);
  317.  
  318.   buf = writePDUType(init->PDUType,buf,len);
  319.   buf = writeBoolean(init->Result,buf,len);
  320.   buf = writeProtocolVersion(buf,len);
  321.  
  322.   optionsBM = makeBitMap((unsigned long)5,init->willSearch,init->willPresent,
  323.                          init->willDelete,init->supportAccessControl,
  324.                          init->supportResourceControl);
  325.   buf = writeBitMap(optionsBM,DT_Options,buf,len);
  326.   freeBitMap(optionsBM);
  327.  
  328.   buf = writeNum(init->PreferredMessageSize,DT_PreferredMessageSize,buf,len);
  329.   buf = writeNum(init->MaximumRecordSize,DT_MaximumRecordSize,buf,len);
  330.   buf = writeString(init->IDAuthentication,DT_IDAuthentication,buf,len);
  331.   buf = writeString(init->ImplementationID,DT_ImplementationID,buf,len);
  332.   buf = writeString(init->ImplementationName,DT_ImplementationName,buf,len);
  333.   buf = writeString(init->ImplementationVersion,DT_ImplementationVersion,buf,len);
  334.   buf = writeAny(init->ReferenceID,DT_ReferenceID,buf,len);
  335.  
  336.   /* go back and write the header-length-indicator */
  337.   RELEASE_HEADER_SPACE(len);
  338.   size = buf - buffer - HEADER_LEN;
  339.   writeBinaryInteger(size,HEADER_LEN,buffer,len);
  340.  
  341.   if (init->UserInformationField != NULL)
  342.     buf = writeInitResponseInfo(init,buf,len);
  343.  
  344.   return(buf);
  345. }
  346.  
  347. /*----------------------------------------------------------------------*/
  348.  
  349. char*
  350. readInitResponseAPDU(init,buffer)
  351. InitResponseAPDU** init;
  352. char* buffer;
  353. {
  354.   char* buf = buffer;
  355.   boolean search,present,delete,accessControl,resourceControl;
  356.   long prefSize,maxMsgSize;
  357.   char *auth,*id,*name,*version;
  358.   long size;
  359.   pdu_type pduType;
  360.   bit_map* versionBM = NULL;
  361.   bit_map* optionsBM = NULL;
  362.   boolean result;
  363.   any *refID = NULL;
  364.   void* userInfo = NULL;
  365.  
  366.   auth = id = name = version = NULL;
  367.   refID = NULL;
  368.  
  369.   /* read required part */
  370.   buf = readBinaryInteger(&size,HEADER_LEN,buf);
  371.   buf = readPDUType(&pduType,buf);
  372.   buf = readBoolean(&result,buf);
  373.   buf = readBitMap(&versionBM,buf);
  374.   buf = readBitMap(&optionsBM,buf);
  375.   buf = readNum(&prefSize,buf);
  376.   buf = readNum(&maxMsgSize,buf);
  377.  
  378.   /* decode optionsBM */
  379.   
  380.   search = bitAtPos(0L,optionsBM);
  381.   present = bitAtPos(1L,optionsBM);
  382.   delete = bitAtPos(2L,optionsBM);
  383.   accessControl = bitAtPos(3L,optionsBM);
  384.   resourceControl = bitAtPos(4L,optionsBM);
  385.  
  386.   /* read optional part */
  387.   while (buf < (buffer + size + HEADER_LEN))
  388.     { data_tag tag = peekTag(buf);
  389.       switch (tag)
  390.         { case DT_IDAuthentication:
  391.             buf = readString(&auth,buf);
  392.             break;
  393.           case DT_ImplementationID:
  394.             buf = readString(&id,buf);
  395.             break;
  396.           case DT_ImplementationName:
  397.             buf = readString(&name,buf);
  398.             break;
  399.           case DT_ImplementationVersion:
  400.             buf = readString(&version,buf);
  401.             break;
  402.           case DT_ReferenceID:
  403.             buf = readAny(&refID,buf);
  404.             break;
  405.           default:
  406.             freeBitMap(versionBM);
  407.             freeBitMap(optionsBM);
  408.             s_free(auth);
  409.             s_free(id);
  410.             s_free(name);
  411.             s_free(version);
  412.             freeAny(refID);
  413.             REPORT_READ_ERROR(buf);
  414.             break;
  415.           }
  416.     }
  417.  
  418.   buf = readInitResponseInfo(&userInfo,buf);
  419.   if (buf == NULL)
  420.     { freeBitMap(versionBM);
  421.       freeBitMap(optionsBM);
  422.       s_free(auth);
  423.       s_free(id);
  424.       s_free(name);
  425.       s_free(version);
  426.       freeAny(refID);
  427.     }
  428.   RETURN_ON_NULL(buf);
  429.  
  430.   /* construct the basic init object */
  431.   *init = makeInitResponseAPDU(result,
  432.                                search,present,delete,accessControl,resourceControl,
  433.                                prefSize,maxMsgSize,auth,id,name,version,refID,userInfo);
  434.  
  435.   freeBitMap(versionBM);
  436.   freeBitMap(optionsBM);
  437.   s_free(auth);
  438.   s_free(id);
  439.   s_free(name);
  440.   s_free(version);
  441.   freeAny(refID);
  442.  
  443.   return(buf);
  444. }
  445.  
  446. /*----------------------------------------------------------------------*/
  447.  
  448. InitResponseAPDU*
  449. replyToInitAPDU(init,result,userInfo)
  450. InitAPDU* init;
  451. boolean result;
  452. void* userInfo;
  453. /* respond to an init message in the default way - echoing back
  454.    the init info
  455.  */
  456. {
  457.   InitResponseAPDU* initResp;
  458.   initResp = makeInitResponseAPDU(result,
  459.                                   init->willSearch,init->willPresent,init->willDelete,
  460.                                   init->supportAccessControl,init->supportResourceControl,
  461.                                   init->PreferredMessageSize,init->MaximumRecordSize,
  462.                                   init->IDAuthentication,defaultImplementationID(),defaultImplementationName(),
  463.                                   defaultImplementationVersion(),
  464.                                   init->ReferenceID,userInfo);
  465.   return(initResp);
  466. }
  467.  
  468. /*----------------------------------------------------------------------*/
  469.  
  470. SearchAPDU*
  471. makeSearchAPDU(small,
  472.                large,
  473.                medium,
  474.                replace,
  475.                name,
  476.                databases,
  477.                type,
  478.                elements,
  479.                refID,
  480.                queryInfo)
  481. long small;
  482. long large;
  483. long medium;
  484. boolean replace;
  485. char* name;
  486. char** databases;
  487. char* type;
  488. char** elements;
  489. any* refID;
  490. void* queryInfo;
  491. {
  492.   char* ptr = NULL;
  493.   long i;
  494.   SearchAPDU* query = (SearchAPDU*)s_malloc((long)sizeof(SearchAPDU));
  495.   query->PDUType = searchAPDU;
  496.   query->SmallSetUpperBound = small;
  497.   query->LargeSetLowerBound = large;
  498.   query->MediumSetPresentNumber = medium;
  499.   query->ReplaceIndicator = replace;
  500.   query->ResultSetName = s_strdup(name);
  501.   query->DatabaseNames = NULL;
  502.   if (databases != NULL)
  503.     { for (i = 0, ptr = databases[i]; ptr != NULL; ptr = databases[++i])
  504.         { if (query->DatabaseNames == NULL)
  505.             query->DatabaseNames = (char**)s_malloc((long)(sizeof(char*) * 2));
  506.         else
  507.           query->DatabaseNames = (char**)s_realloc((char*)query->DatabaseNames,
  508.                                                    (sizeof(char*) * (i + 2)));
  509.             query->DatabaseNames[i] = s_strdup(ptr);
  510.             query->DatabaseNames[i+1] = NULL;
  511.           }
  512.       }
  513.   query->QueryType = s_strdup(type);
  514.   query->ElementSetNames = NULL;
  515.   if (elements != NULL)
  516.     { for (i = 0L, ptr = elements[i]; ptr != NULL; ptr = elements[++i])
  517.         { if (query->ElementSetNames == NULL)
  518.             query->ElementSetNames = (char**)s_malloc((long)(sizeof(char*) * 2));
  519.         else
  520.           query->ElementSetNames = (char**)s_realloc((char*)query->ElementSetNames,
  521.                                                      (sizeof(char*) * (i + 2)));
  522.             query->ElementSetNames[i] = s_strdup(ptr);
  523.             query->ElementSetNames[i+1] = NULL;
  524.           }
  525.       }
  526.   query->ReferenceID = duplicateAny(refID);
  527.   query->Query = queryInfo;     /* not copied! */
  528.   return(query);
  529. }
  530.  
  531. /*----------------------------------------------------------------------*/
  532.  
  533. void
  534. freeSearchAPDU(query)
  535. SearchAPDU* query;
  536. {
  537.   s_free(query->ResultSetName);
  538.   s_free(query->QueryType);
  539.   doList((void**)query->DatabaseNames,fs_free); /* can't use the macro here ! */
  540.   s_free(query->DatabaseNames);
  541.   doList((void**)query->ElementSetNames,fs_free); /* can't use the macro here ! */
  542.   s_free(query->ElementSetNames);
  543.   freeAny(query->ReferenceID);
  544.   s_free(query);
  545. }
  546.  
  547. /*----------------------------------------------------------------------*/
  548.  
  549. #define DB_DELIMITER    "\037"  /* hex 1F occurs between each database name */
  550. #define ES_DELIMITER_1  "\037"  /* separates database name from element name */
  551. #define ES_DELIMITER_2  "\036"  /* hex 1E separates <db,es> groups from one another */
  552.  
  553. char*
  554. writeSearchAPDU(query,buffer,len)
  555. SearchAPDU* query;
  556. char* buffer;
  557. long* len;
  558. {
  559.   char* buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
  560.   long size,i;
  561.   char* ptr = NULL;
  562.   char* scratch = NULL;
  563.  
  564.   RESERVE_SPACE_FOR_HEADER(len);
  565.  
  566.   buf = writePDUType(query->PDUType,buf,len);
  567.  
  568.   buf = writeBinaryInteger(query->SmallSetUpperBound,3L,buf,len);
  569.   buf = writeBinaryInteger(query->LargeSetLowerBound,3L,buf,len);
  570.   buf = writeBinaryInteger(query->MediumSetPresentNumber,3L,buf,len);
  571.  
  572.   buf = writeBoolean(query->ReplaceIndicator,buf,len);
  573.   buf = writeString(query->ResultSetName,DT_ResultSetName,buf,len);
  574.   /* write database names */
  575.   if (query->DatabaseNames != NULL)
  576.     { for (i = 0,scratch = NULL, ptr = query->DatabaseNames[i]; ptr != NULL; ptr = query->DatabaseNames[++i])
  577.         { if (scratch == NULL)
  578.             scratch = s_strdup(ptr);
  579.         else
  580.           { long newScratchSize = (long)(strlen(scratch) + strlen(ptr) + 2);
  581.             scratch = (char*)s_realloc(scratch,newScratchSize);
  582.             s_strncat(scratch,DB_DELIMITER,2L,newScratchSize);
  583.             s_strncat(scratch,ptr,(long)strlen(ptr) + 1,newScratchSize);
  584.           }
  585.           }
  586.         buf = writeString(scratch,DT_DatabaseNames,buf,len);
  587.         s_free(scratch);
  588.       }
  589.   buf = writeString(query->QueryType,DT_QueryType,buf,len);
  590.   /* write element set names */
  591.   if (query->ElementSetNames != NULL)
  592.     { for (i = 0,scratch = NULL, ptr = query->ElementSetNames[i]; ptr != NULL; ptr = query->ElementSetNames[++i])
  593.         { if (scratch == NULL)
  594.             { if (query->ElementSetNames[i+1] == NULL) /* there is a single element set name */
  595.                 { scratch = (char*)s_malloc((long)(strlen(ptr) + 2));
  596.                   strncpy(scratch,ES_DELIMITER_1,2);
  597.                   s_strncat(scratch,ptr,(long)strlen(ptr) + 1,(long)strlen(ptr) + 2);
  598.                 }
  599.             else                /* this is the first of a series of element set names */
  600.               { long newScratchSize = (long)(strlen(ptr) + strlen(query->ElementSetNames[i + 1]) + 2);
  601.                 scratch = s_strdup(ptr); /* the database name */
  602.                 ptr = query->ElementSetNames[++i]; /* the element set name */
  603.                 scratch = (char*)s_realloc(scratch,newScratchSize);
  604.                 s_strncat(scratch,ES_DELIMITER_1,2L,newScratchSize);
  605.                 s_strncat(scratch,ptr,(long)strlen(ptr) + 1,newScratchSize);
  606.               }
  607.               }
  608.         else
  609.           { char* esPtr = query->ElementSetNames[++i]; /* the element set name */
  610.             long newScratchSize = (long)(strlen(scratch) + strlen(ptr) + strlen(esPtr) + 3);
  611.             scratch = (char*)s_realloc(scratch,newScratchSize);
  612.             s_strncat(scratch,ES_DELIMITER_2,2L,newScratchSize);
  613.             s_strncat(scratch,ptr,(long)strlen(ptr) + 1,newScratchSize);
  614.             s_strncat(scratch,ES_DELIMITER_1,2L,newScratchSize);
  615.             s_strncat(scratch,esPtr,(long)strlen(esPtr) + 1,newScratchSize);
  616.           }
  617.           }
  618.         buf = writeString(scratch,DT_ElementSetNames,buf,len);
  619.         s_free(scratch);
  620.       }
  621.   buf = writeAny(query->ReferenceID,DT_ReferenceID,buf,len);
  622.  
  623.   /* go back and write the header-length-indicator */
  624.   RELEASE_HEADER_SPACE(len);
  625.   size = buf - buffer - HEADER_LEN;
  626.   writeBinaryInteger(size,HEADER_LEN,buffer,len);
  627.  
  628.   if (query->Query != NULL)
  629.     buf = writeSearchInfo(query,buf,len);
  630.  
  631.   return(buf);
  632. }
  633.  
  634. /*----------------------------------------------------------------------*/
  635.  
  636. char*
  637. readSearchAPDU(query,buffer)
  638. SearchAPDU** query;
  639. char* buffer;
  640. {
  641.   char* buf = buffer;
  642.   long size;
  643.   pdu_type pduType;
  644.   long small,large,medium,numItems;
  645.   boolean replace;
  646.   char *name,*databaseNames,*type,*elements;
  647.   char **dbList,**elemList;
  648.   any *refID;
  649.   void* userInfo = NULL;
  650.  
  651.   name = databaseNames = type = elements = NULL;
  652.   dbList = elemList = NULL;
  653.   refID = NULL;
  654.  
  655.   /* read required part */
  656.   buf = readBinaryInteger(&size,HEADER_LEN,buf);
  657.   buf = readPDUType(&pduType,buf);
  658.   
  659.   buf = readBinaryInteger(&small,3L,buf);
  660.   buf = readBinaryInteger(&large,3L,buf);
  661.   buf = readBinaryInteger(&medium,3L,buf);
  662.  
  663.   buf = readBoolean(&replace,buf);
  664.  
  665.   /* read optional part */
  666.   while (buf < (buffer + size + HEADER_LEN))
  667.     { data_tag tag = peekTag(buf);
  668.       switch (tag)
  669.         { case DT_ResultSetName:
  670.             buf = readString(&name,buf);
  671.             break;
  672.           case DT_DatabaseNames:
  673.             {                   /* parse the database names */
  674.               char *tok;
  675.               buf = readString(&databaseNames,buf);
  676.               tok = strtok(databaseNames,DB_DELIMITER);
  677.               numItems = 0;
  678.               while (tok != NULL)
  679.                 { if (dbList == NULL)
  680.                     dbList = (char**)s_malloc((long)(sizeof(char*) * 2));
  681.                 else
  682.                   dbList = (char**)s_realloc((char*)dbList,(sizeof(char*) * (numItems+2)));
  683.                     dbList[numItems++] = s_strdup(tok);
  684.                     dbList[numItems] = NULL;
  685.                     tok = strtok(NULL,DB_DELIMITER);
  686.                   }
  687.             }
  688.             break;
  689.           case DT_QueryType:
  690.             buf = readString(&type,buf);
  691.             break;
  692.           case DT_ElementSetNames:
  693.             {                   /* parse the element set names */
  694.               char *tok;
  695.               buf = readString(&elements,buf);
  696.               if (elements[0] == ES_DELIMITER_1[0]) /* this is a single element w/ no db */
  697.                 { elemList = (char**)s_malloc((long)(sizeof(char*) * 2));
  698.                   elemList[0] = s_strdup(elements);
  699.                   elemList[1] = NULL;
  700.                 }
  701.               else              /* its a group of <DB/ES> pairs */
  702.                 { char* esTok = NULL;
  703.                   tok = strtok(elements,ES_DELIMITER_1); /* db name */
  704.                   esTok = strtok(NULL,ES_DELIMITER_2); /* es name */
  705.                   numItems = 0;
  706.                   while (tok != NULL)
  707.                     { if (elemList == NULL)
  708.                         elemList = (char**)s_malloc((long)(sizeof(char*) * 3));
  709.                     else
  710.                       elemList = (char**)s_realloc((char*)elemList,(sizeof(char*) * (numItems * 2 + 1)));
  711.                         elemList[numItems++] = s_strdup(tok);
  712.                         elemList[numItems++] = s_strdup(esTok);
  713.                         elemList[numItems] = NULL;
  714.                         tok = strtok(NULL,ES_DELIMITER_1);
  715.                         esTok = strtok(NULL,ES_DELIMITER_2);
  716.                       }
  717.                 }
  718.             }
  719.             break;
  720.           case DT_ReferenceID:
  721.             buf = readAny(&refID,buf);
  722.             break;
  723.           default:
  724.             s_free(name);
  725.             s_free(type);
  726.             s_free(databaseNames);
  727.             doList((void**)dbList,fs_free);
  728.             s_free(dbList);
  729.             s_free(elements);
  730.             doList((void**)elemList,fs_free);
  731.             s_free(elemList);
  732.             freeAny(refID);
  733.             REPORT_READ_ERROR(buf);
  734.             break;
  735.           }
  736.     }
  737.  
  738.   buf = readSearchInfo(&userInfo,buf);
  739.   if (buf == NULL)
  740.     { s_free(name);
  741.       s_free(type);
  742.       s_free(databaseNames);
  743.       doList((void**)dbList,fs_free);
  744.       s_free(dbList);
  745.       s_free(elements);
  746.       doList((void**)elemList,fs_free);
  747.       s_free(elemList);
  748.       freeAny(refID);
  749.     }
  750.   RETURN_ON_NULL(buf);
  751.  
  752.   /* construct the search object */
  753.   *query = makeSearchAPDU(small,large,medium,replace,name,dbList,type,elemList,refID,userInfo);
  754.  
  755.   s_free(name);
  756.   s_free(type);
  757.   s_free(databaseNames);
  758.   doList((void**)dbList,fs_free);
  759.   s_free(dbList);
  760.   s_free(elements);
  761.   doList((void**)elemList,fs_free);
  762.   s_free(elemList);
  763.   freeAny(refID);
  764.  
  765.   return(buf);
  766. }
  767.  
  768. /*----------------------------------------------------------------------*/
  769.  
  770. SearchResponseAPDU*
  771. makeSearchResponseAPDU(result,count,recordsReturned,nextPos,resultStatus,
  772.                        presentStatus,refID,records)
  773. long result;
  774. long count;
  775. long recordsReturned;
  776. long nextPos;
  777. long resultStatus;
  778. long presentStatus;
  779. any* refID;
  780. void* records;
  781. {
  782.   SearchResponseAPDU* query = (SearchResponseAPDU*)s_malloc((long)sizeof(SearchResponseAPDU));
  783.   query->PDUType = searchResponseAPDU;
  784.   query->SearchStatus = result;
  785.   query->ResultCount = count;
  786.   query->NumberOfRecordsReturned = recordsReturned;
  787.   query->NextResultSetPosition = nextPos;
  788.   query->ResultSetStatus = resultStatus;
  789.   query->PresentStatus = presentStatus;
  790.   query->ReferenceID = duplicateAny(refID);
  791.   query->DatabaseDiagnosticRecords = records;
  792.   return(query);
  793. }
  794.  
  795. /*----------------------------------------------------------------------*/
  796.  
  797. void
  798. freeSearchResponseAPDU(queryResponse)
  799. SearchResponseAPDU* queryResponse;
  800. {
  801.   freeAny(queryResponse->ReferenceID);
  802.   s_free(queryResponse);
  803. }
  804.  
  805. /*----------------------------------------------------------------------*/
  806.  
  807. char*
  808. writeSearchResponseAPDU(queryResponse,buffer,len)
  809. SearchResponseAPDU* queryResponse;
  810. char* buffer;
  811. long* len;
  812. {
  813.   char* buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
  814.   long size;
  815.  
  816.   RESERVE_SPACE_FOR_HEADER(len);
  817.  
  818.   buf = writePDUType(queryResponse->PDUType,buf,len);
  819.  
  820.   buf = writeBinaryInteger(queryResponse->SearchStatus,1L,buf,len);
  821.   buf = writeBinaryInteger(queryResponse->ResultCount,3L,buf,len);
  822.   buf = writeBinaryInteger(queryResponse->NumberOfRecordsReturned,3L,buf,len);
  823.   buf = writeBinaryInteger(queryResponse->NextResultSetPosition,3L,buf,len);
  824.  
  825.   buf = writeNum(queryResponse->ResultSetStatus,DT_ResultSetStatus,buf,len);
  826.   buf = writeNum(queryResponse->PresentStatus,DT_PresentStatus,buf,len);
  827.   buf = writeAny(queryResponse->ReferenceID,DT_ReferenceID,buf,len);
  828.  
  829.   /* go back and write the header-length-indicator */
  830.   RELEASE_HEADER_SPACE(len);
  831.   size = buf - buffer - HEADER_LEN;
  832.   writeBinaryInteger(size,HEADER_LEN,buffer,len);
  833.  
  834.   if (queryResponse->DatabaseDiagnosticRecords != 0)
  835.     buf = writeSearchResponseInfo(queryResponse,buf,len);
  836.  
  837.   return(buf);
  838. }
  839.  
  840. /*----------------------------------------------------------------------*/
  841.  
  842. char*
  843. readSearchResponseAPDU(queryResponse,buffer)
  844. SearchResponseAPDU** queryResponse;
  845. char* buffer;
  846. {
  847.   char* buf = buffer;
  848.   long size;
  849.   pdu_type pduType;
  850.   long result,count,recordsReturned,nextPos;
  851.   long resultStatus,presentStatus;
  852.   any *refID = NULL;
  853.   void* userInfo = NULL;
  854.  
  855.   /* read required part */
  856.   buf = readBinaryInteger(&size,HEADER_LEN,buf);
  857.   buf = readPDUType(&pduType,buf);
  858.  
  859.   buf = readBinaryInteger(&result,1L,buf);
  860.   buf = readBinaryInteger(&count,3L,buf);
  861.   buf = readBinaryInteger(&recordsReturned,3L,buf);
  862.   buf = readBinaryInteger(&nextPos,3L,buf);
  863.  
  864.   resultStatus = presentStatus = UNUSED;
  865.   refID = NULL;
  866.  
  867.   /* read optional part */
  868.   while (buf < (buffer + size + HEADER_LEN))
  869.     { data_tag tag = peekTag(buf);
  870.       switch (tag)
  871.         { case DT_ResultSetStatus:
  872.             buf = readNum(&resultStatus,buf);
  873.             break;
  874.           case DT_PresentStatus:
  875.             buf = readNum(&presentStatus,buf);
  876.             break;
  877.           case DT_ReferenceID:
  878.             buf = readAny(&refID,buf);
  879.             break;
  880.           default:
  881.             freeAny(refID);
  882.             REPORT_READ_ERROR(buf);
  883.             break;
  884.           }
  885.     }
  886.  
  887.   buf = readSearchResponseInfo(&userInfo,buf);
  888.   if (buf == NULL)
  889.     freeAny(refID);
  890.   RETURN_ON_NULL(buf);
  891.  
  892.   /* construct the search object */
  893.   *queryResponse = makeSearchResponseAPDU(result,count,recordsReturned,nextPos,
  894.                                           (long)resultStatus,(long)presentStatus,refID,userInfo);
  895.  
  896.   freeAny(refID);
  897.  
  898.   return(buf);
  899. }
  900.  
  901. #ifdef NOTUSED
  902. /*----------------------------------------------------------------------*/
  903.  
  904.  
  905. PresentAPDU*
  906. makePresentAPDU(recsReq,startPos,resultID,refID,info)
  907. long recsReq;
  908. long startPos;
  909. char* resultID;
  910. any* refID;
  911. void* info;
  912. {
  913.   PresentAPDU* present = (PresentAPDU*)s_malloc((long)sizeof(PresentAPDU));
  914.   present->PDUType = presentAPDU;
  915.   present->NumberOfRecordsRequested = recsReq;
  916.   present->ResultSetStartPosition = startPos;
  917.   present->ResultSetID = s_strdup(resultID);
  918.   present->ElementSetNames = NULL; /* XXX for now */
  919.   present->ReferenceID = duplicateAny(refID);
  920.   present->PresentInfo = info;
  921.   return(present);
  922. }
  923.  
  924. /*----------------------------------------------------------------------*/
  925.  
  926. void
  927. freePresentAPDU(present)
  928. PresentAPDU* present;
  929. {
  930.   /* handle element set names */
  931.   s_free(present->ResultSetID);
  932.   freeAny(present->ReferenceID);
  933.   s_free(present);
  934. }
  935.  
  936. /*----------------------------------------------------------------------*/
  937.  
  938. char*
  939. writePresentAPDU(present,buffer,len)
  940. PresentAPDU* present;
  941. char* buffer;
  942. long* len;
  943. {
  944.   char* buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
  945.   long size;
  946.  
  947.   RESERVE_SPACE_FOR_HEADER(len);
  948.  
  949.   buf = writePDUType(present->PDUType,buf,len);
  950.  
  951.   buf = writeBinaryInteger(present->NumberOfRecordsRequested,3L,buf,len);
  952.   buf = writeBinaryInteger(present->ResultSetStartPosition,3L,buf,len);
  953.  
  954.   buf = writeString(present->ResultSetID,DT_ResultSetID,buf,len);
  955.   /* handle element set names */
  956.   buf = writeAny(present->ReferenceID,DT_ReferenceID,buf,len);
  957.  
  958.   /* go back and write the header-length-indicator */
  959.   RELEASE_HEADER_SPACE(len);
  960.   size = buf - buffer - HEADER_LEN;
  961.   writeBinaryInteger(size,HEADER_LEN,buffer,len);
  962.  
  963.   if (present->PresentInfo != NULL)
  964.     buf = writePresentInfo(present,buf,len);
  965.  
  966.   return(buf);
  967. }
  968.  
  969. /*----------------------------------------------------------------------*/
  970.  
  971. char*
  972. readPresentAPDU(present,buffer)
  973. PresentAPDU** present;
  974. char* buffer;
  975. {
  976.   char* buf = buffer;
  977.   long size;
  978.   pdu_type pduType;
  979.   long recsReq,startPos;
  980.   char* resultID = NULL;
  981.   any *refID = NULL;
  982.   void* userInfo = NULL;
  983.  
  984.   /* read required part */
  985.   buf = readBinaryInteger(&size,HEADER_LEN,buf);
  986.   buf = readPDUType(&pduType,buf);
  987.  
  988.   buf = readBinaryInteger(&recsReq,3L,buf);
  989.   buf = readBinaryInteger(&startPos,3L,buf);
  990.  
  991.   buf = readString(&resultID,buf);
  992.  
  993.   /* read optional part */
  994.   while (buf < (buffer + size + HEADER_LEN))
  995.    { data_tag tag = peekTag(buf);
  996.      switch (tag)
  997.       { case DT_ReferenceID:
  998.           buf = readAny(&refID,buf);
  999.           break;
  1000.         default:
  1001.           s_free(resultID);
  1002.           freeAny(refID);
  1003.           REPORT_READ_ERROR(buf);
  1004.           break;
  1005.       }
  1006.    }
  1007.  
  1008.   buf = readPresentInfo(&userInfo,buf);
  1009.   if (buf == NULL)
  1010.    { s_free(resultID);
  1011.      freeAny(refID);
  1012.    }
  1013.   RETURN_ON_NULL(buf);
  1014.  
  1015.   /* construct the present object */
  1016.   *present = makePresentAPDU(recsReq,startPos,resultID,refID,userInfo);
  1017.  
  1018.   s_free(resultID);
  1019.   freeAny(refID);
  1020.  
  1021.   return(buf);
  1022. }
  1023.  
  1024. /*----------------------------------------------------------------------*/
  1025.  
  1026.  
  1027. PresentResponseAPDU*
  1028. makePresentResponseAPDU(status,recsRet,nextPos,refID,records)
  1029. boolean status;
  1030. long recsRet;
  1031. long nextPos;
  1032. any* refID;
  1033. void* records;
  1034. {
  1035.   PresentResponseAPDU* present = (PresentResponseAPDU*)s_malloc((long)sizeof(PresentResponseAPDU));
  1036.   present->PDUType = presentResponseAPDU;
  1037.   present->PresentStatus = status;
  1038.   present->NumberOfRecordsReturned = recsRet;
  1039.   present->NextResultSetPosition = nextPos;
  1040.   present->ReferenceID = duplicateAny(refID);
  1041.   present->DatabaseDiagnosticRecords = records;
  1042.   return(present);
  1043. }
  1044.  
  1045. /*----------------------------------------------------------------------*/
  1046.  
  1047. void
  1048. freePresentResponseAPDU(present)
  1049. PresentResponseAPDU* present;
  1050. {
  1051.   freeAny(present->ReferenceID);
  1052.   s_free(present);
  1053. }
  1054.  
  1055. /*----------------------------------------------------------------------*/
  1056.  
  1057. char*
  1058. writePresentResponseAPDU(present,buffer,len)
  1059. PresentResponseAPDU* present;
  1060. char* buffer;
  1061. long* len;
  1062. {
  1063.   char* buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
  1064.   long size;
  1065.  
  1066.   RESERVE_SPACE_FOR_HEADER(len);
  1067.  
  1068.   buf = writePDUType(present->PDUType,buf,len);
  1069.   buf = writeBoolean(present->PresentStatus,buf,len);
  1070.  
  1071.   buf = writeBinaryInteger(present->NumberOfRecordsReturned,3L,buf,len);
  1072.   buf = writeBinaryInteger(present->NextResultSetPosition,3L,buf,len);
  1073.  
  1074.   buf = writeAny(present->ReferenceID,DT_ReferenceID,buf,len);
  1075.  
  1076.   /* go back and write the header-length-indicator */
  1077.   RELEASE_HEADER_SPACE(len);
  1078.   size = buf - buffer - HEADER_LEN;
  1079.   writeBinaryInteger(size,HEADER_LEN,buffer,len);
  1080.  
  1081.   if (present->DatabaseDiagnosticRecords != 0)
  1082.     buf = writePresentResponseInfo(present,buf,len);
  1083.  
  1084.   return(buf);
  1085. }
  1086.  
  1087. /*----------------------------------------------------------------------*/
  1088.  
  1089. char*
  1090. readPresentResponseAPDU(present,buffer)
  1091. PresentResponseAPDU** present;
  1092. char* buffer;
  1093. {
  1094.   char* buf = buffer;
  1095.   long size;
  1096.   pdu_type pduType;
  1097.   boolean status;
  1098.   long recsRet,nextPos;
  1099.   any *refID = NULL;
  1100.   void* userInfo = NULL;
  1101.  
  1102.   /* read required part */
  1103.   buf = readBinaryInteger(&size,HEADER_LEN,buf);
  1104.   buf = readPDUType(&pduType,buf);
  1105.   buf = readBoolean(&status,buf);
  1106.  
  1107.   buf = readBinaryInteger(&recsRet,3L,buf);
  1108.   buf = readBinaryInteger(&nextPos,3L,buf);
  1109.  
  1110.   /* read optional part */
  1111.   while (buf < (buffer + size + HEADER_LEN))
  1112.    { data_tag tag = peekTag(buf);
  1113.      switch (tag)
  1114.       { case DT_ReferenceID:
  1115.           buf = readAny(&refID,buf);
  1116.           break;
  1117.         default:
  1118.           freeAny(refID);
  1119.           REPORT_READ_ERROR(buf);
  1120.           break;
  1121.       }
  1122.    }
  1123.  
  1124.   buf = readPresentResponseInfo(&userInfo,buf);
  1125.   if (buf == NULL)
  1126.     freeAny(refID);
  1127.   RETURN_ON_NULL(buf);
  1128.  
  1129.   /* construct the presentResponse object */
  1130.   *present = makePresentResponseAPDU(status,recsRet,nextPos,refID,userInfo);
  1131.  
  1132.   freeAny(refID);
  1133.  
  1134.   return(buf);
  1135. }
  1136.  
  1137. /*----------------------------------------------------------------------*/
  1138.  
  1139.  
  1140. #endif /* def NOTUSED */
  1141.