uniqueid.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. #ifdef HAVE_CONFIG_H
  39. # include <config.h>
  40. #endif
  41. /* uniqueid.c implementation of entryid functionality */
  42. #include <stdlib.h>
  43. #include <stdio.h>
  44. #include <string.h>
  45. #include <ctype.h>
  46. #include "slap.h"
  47. #define UIDSTR_SIZE 35 /* size of the string representation of the id */
  48. #define MODULE "uniqueid" /* for logging */
  49. static int isValidFormat (const char * buff);
  50. static PRUint8 str2Byte (const char *str);
  51. /* All functions that strat with slapi_ are exposed to the plugins */
  52. /* Function: slapi_uniqueIDNew
  53. Description: creates new Slapi_UniqueID object
  54. Parameters: none
  55. Return: pointer to the new uId object if successful
  56. NULL if memory allocation failed
  57. */
  58. Slapi_UniqueID *slapi_uniqueIDNew ()
  59. {
  60. Slapi_UniqueID *uId;
  61. uId = (Slapi_UniqueID*)slapi_ch_malloc (sizeof (Slapi_UniqueID));
  62. if (uId == NULL)
  63. {
  64. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "uniqueIDNew: "
  65. "failed to allocate new id.\n");
  66. return NULL;
  67. }
  68. memset (uId, 0, sizeof (Slapi_UniqueID));
  69. return uId;
  70. }
  71. /* Function: slapi_uniqueIDDestroy
  72. Description: destroys Slapi_UniqueID objects and sets the pointer to NULL
  73. Parameters: uId - id to destroy
  74. Return: none
  75. */
  76. void slapi_uniqueIDDestroy (Slapi_UniqueID **uId)
  77. {
  78. if (uId && *uId)
  79. {
  80. slapi_ch_free ((void**)uId);
  81. *uId = NULL;
  82. }
  83. }
  84. /* Function: slapi_uniqueIDCompare
  85. Description: this function lexically compares two entry ids.
  86. both Ids must have UUID type.
  87. Parameters: uId1, uId2 - ids to compare
  88. Return: -1 if uId1 < uId2
  89. 0 if uId2 == uId2
  90. 1 if uId2 > uId2
  91. UID_BADDATA if invalid pointer passed to the function
  92. */
  93. int slapi_uniqueIDCompare (const Slapi_UniqueID *uId1, const Slapi_UniqueID *uId2){
  94. if (uId1 == NULL || uId2 == NULL)
  95. {
  96. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "uniqueIDCompare: "
  97. "NULL argument passed to the function.\n");
  98. return UID_BADDATA;
  99. }
  100. return(uuid_compare(uId1, uId2));
  101. }
  102. /* Function: slapi_uniqueIDCompareString
  103. Description: this function compares two uniqueids, represented as strings
  104. Parameters: uuid1, uuid2 - ids to compare
  105. Return: 0 if uuid1 == uuid2
  106. non-zero if uuid1 != uuid2 or uuid1 == NULL or uuid2 == NULL
  107. */
  108. int slapi_uniqueIDCompareString(const char *uuid1, const char *uuid2)
  109. {
  110. int return_value = 0; /* assume not equal */
  111. if (NULL != uuid1)
  112. {
  113. if (NULL != uuid2)
  114. {
  115. if (strcmp(uuid1, uuid2) == 0)
  116. {
  117. return_value = 1;
  118. }
  119. }
  120. }
  121. return return_value;
  122. }
  123. /* Function: slapi_uniqueIDFormat
  124. Description: this function converts Slapi_UniqueID to its string representation.
  125. The id format is HHHHHHHH-HHHHHHHH-HHHHHHHH-HHHHHHHH
  126. where H is a hex digit. The data will be outputed in the
  127. network byte order.
  128. Parameters: uId - entry id
  129. buff - buffer in which id is returned; caller must free this
  130. buffer
  131. Return: UID_SUCCESS - function was successfull
  132. UID_BADDATA - invalid parameter passed to the function
  133. UID_MEMORY_ERROR - failed to allocate the buffer
  134. */
  135. int slapi_uniqueIDFormat (const Slapi_UniqueID *uId, char **buff){
  136. guid_t uuid_tmp;
  137. if (uId == NULL || buff == NULL)
  138. {
  139. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "uniqueIDFormat: "
  140. "NULL argument passed to the function.\n");
  141. return UID_BADDATA;
  142. }
  143. *buff = (char*)slapi_ch_malloc (UIDSTR_SIZE + 1);
  144. if (*buff == NULL)
  145. {
  146. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "uniqueIDFormat: "
  147. "failed to allocate buffer.\n");
  148. return UID_MEMORY_ERROR;
  149. }
  150. uuid_tmp = *uId;
  151. uuid_tmp.time_low = htonl(uuid_tmp.time_low);
  152. uuid_tmp.time_mid = htons(uuid_tmp.time_mid);
  153. uuid_tmp.time_hi_and_version = htons(uuid_tmp.time_hi_and_version);
  154. sprintf (*buff, "%2.2x%2.2x%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x-"
  155. "%2.2x%2.2x%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x",
  156. ((PRUint8 *) &uuid_tmp.time_low)[0], ((PRUint8 *) &uuid_tmp.time_low)[1],
  157. ((PRUint8 *) &uuid_tmp.time_low)[2], ((PRUint8 *) &uuid_tmp.time_low)[3],
  158. ((PRUint8 *) &uuid_tmp.time_mid)[0], ((PRUint8 *) &uuid_tmp.time_mid)[1],
  159. ((PRUint8 *) &uuid_tmp.time_hi_and_version)[0],
  160. ((PRUint8 *) &uuid_tmp.time_hi_and_version)[1],
  161. uuid_tmp.clock_seq_hi_and_reserved, uuid_tmp.clock_seq_low,
  162. uuid_tmp.node[0], uuid_tmp.node[1], uuid_tmp.node[2],
  163. uuid_tmp.node[3], uuid_tmp.node[4], uuid_tmp.node[5]);
  164. return UID_SUCCESS;
  165. }
  166. /* Function: slapi_uniqueIDScan
  167. Description: this function converts a string buffer into uniqueID.
  168. Parameters: uId - unique id to be returned
  169. buff - buffer with uniqueID in the format returned by
  170. uniqueIDFormat function
  171. Return: UID_SUCCESS - function was successfull
  172. UID_BADDATA - null parameter(s) or bad format
  173. */
  174. int slapi_uniqueIDScan (Slapi_UniqueID *uId, const char *buff){
  175. if (uId == NULL || buff == NULL)
  176. {
  177. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "uniqueIDScan: "
  178. "NULL argument passed to the function.\n");
  179. return UID_BADDATA;
  180. }
  181. if (!isValidFormat (buff))
  182. {
  183. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "uniqueIDScan: "
  184. "invalid data format.\n");
  185. return UID_BADDATA;
  186. }
  187. ((PRUint8 *) &uId->time_low)[0] = str2Byte (&(buff[0]));
  188. ((PRUint8 *) &uId->time_low)[1] = str2Byte (&(buff[2]));
  189. ((PRUint8 *) &uId->time_low)[2] = str2Byte (&(buff[4]));
  190. ((PRUint8 *) &uId->time_low)[3] = str2Byte (&(buff[6]));
  191. /* next field is at 9 because we skip the - */
  192. ((PRUint8 *) &uId->time_mid)[0] = str2Byte (&(buff[9]));
  193. ((PRUint8 *) &uId->time_mid)[1] = str2Byte (&(buff[11]));
  194. ((PRUint8 *) &uId->time_hi_and_version)[0] = str2Byte (&(buff[13]));
  195. ((PRUint8 *) &uId->time_hi_and_version)[1] = str2Byte (&(buff[15]));
  196. /* next field is at 18 because we skip the - */
  197. uId->clock_seq_hi_and_reserved = str2Byte (&(buff[18]));
  198. uId->clock_seq_low = str2Byte (&(buff[20]));
  199. uId->node[0] = str2Byte (&(buff[22]));
  200. uId->node[1] = str2Byte (&(buff[24]));
  201. /* next field is at 27 because we skip the - */
  202. uId->node[2] = str2Byte (&(buff[27]));
  203. uId->node[3] = str2Byte (&(buff[29]));
  204. uId->node[4] = str2Byte (&(buff[31]));
  205. uId->node[5] = str2Byte (&(buff[33]));
  206. uId->time_low = ntohl(uId->time_low);
  207. uId->time_mid = ntohs(uId->time_mid);
  208. uId->time_hi_and_version = ntohs(uId->time_hi_and_version);
  209. return UID_SUCCESS;
  210. }
  211. /* Function: slapi_uniqueIDIsUUID
  212. Description: tests if given entry id is in UUID format
  213. Parameters: uId - id to test
  214. Return 0 - it is UUID
  215. 1 - it is not UUID
  216. UID_BADDATA - invalid data passed to the function
  217. Note: LPXXX - This call is not used currently. Keep it ???
  218. */
  219. int slapi_uniqueIDIsUUID (const Slapi_UniqueID *uId){
  220. if (uId == NULL)
  221. return UID_BADDATA;
  222. /* Shortening Slapi_UniqueID: This call does nothing */
  223. return (0);
  224. }
  225. /* Name: slapi_uniqueIDSize
  226. Description: returns size of the string version of uniqueID in bytes
  227. Parameters: none
  228. Return: size of the string version of uniqueID in bytes
  229. */
  230. int slapi_uniqueIDSize ()
  231. {
  232. return (UIDSTR_SIZE);
  233. }
  234. /* Name: slapi_uniqueIDDup
  235. Description: duplicates an UniqueID object
  236. Parameters: uId - id to duplicate
  237. Return: duplicate of the Id
  238. */
  239. Slapi_UniqueID* slapi_uniqueIDDup (Slapi_UniqueID *uId)
  240. {
  241. Slapi_UniqueID *uIdDup = slapi_uniqueIDNew ();
  242. memcpy (uIdDup, uId, sizeof (Slapi_UniqueID));
  243. return uIdDup;
  244. }
  245. /* helper functions */
  246. static char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7',
  247. '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', '\0'};
  248. /* this function converts a string representation of a byte in hex into
  249. an actual byte. For instance: "AB" -> 171 */
  250. static PRUint8 str2Byte (const char *str)
  251. {
  252. char letter1 = str[0];
  253. char letter2 = str[1];
  254. PRUint8 num = 0;
  255. int i = 0;
  256. while (hexDigits[i] != '\0')
  257. {
  258. if (letter1 == hexDigits[i] || toupper (letter1) == hexDigits[i])
  259. {
  260. num |= (i << 4);
  261. }
  262. if (letter2 == hexDigits[i] || toupper (letter2) == hexDigits[i])
  263. {
  264. num |= i;
  265. }
  266. i++;
  267. }
  268. return num;
  269. }
  270. static char* format = "XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX";
  271. /* This function verifies that buff contains data in the correct
  272. format (specified above). */
  273. static int isValidFormat (const char * buff)
  274. {
  275. int len;
  276. int i;
  277. if (strlen (buff) != strlen (format))
  278. return UID_BADDATA;
  279. len = strlen (format);
  280. for (i = 0; i < len; i++)
  281. {
  282. if (format[i] == '-' && buff [i] != '-')
  283. return 0;
  284. else if (format[i] == 'X' && ! isxdigit (buff[i]))
  285. return 0;
  286. }
  287. return 1;
  288. }