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