home *** CD-ROM | disk | FTP | other *** search
/ Internet Publisher's Toolbox 2.0 / Internet Publisher's Toolbox.iso / internet / ntserver / wtsource / zprot.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-16  |  32.5 KB  |  1,144 lines

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