uniqueid.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  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. /* uniqueid.c implementation of entryid functionality */
  39. #include <stdlib.h>
  40. #include <stdio.h>
  41. #include <string.h>
  42. #include <ctype.h>
  43. #include "slap.h"
  44. #define UIDSTR_SIZE 35 /* size of the string representation of the id */
  45. #define MODULE "uniqueid" /* for logging */
  46. static int isValidFormat (const char * buff);
  47. static PRUint8 str2Byte (const char *str);
  48. /* All functions that strat with slapi_ are exposed to the plugins */
  49. /* Function: slapi_uniqueIDNew
  50. Description: creates new Slapi_UniqueID object
  51. Parameters: none
  52. Return: pointer to the new uId object if successful
  53. NULL if memory allocation failed
  54. */
  55. Slapi_UniqueID *slapi_uniqueIDNew ()
  56. {
  57. Slapi_UniqueID *uId;
  58. uId = (Slapi_UniqueID*)slapi_ch_malloc (sizeof (Slapi_UniqueID));
  59. if (uId == NULL)
  60. {
  61. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "uniqueIDNew: "
  62. "failed to allocate new id.\n");
  63. return NULL;
  64. }
  65. memset (uId, 0, sizeof (Slapi_UniqueID));
  66. return uId;
  67. }
  68. /* Function: slapi_uniqueIDDestroy
  69. Description: destroys Slapi_UniqueID objects and sets the pointer to NULL
  70. Parameters: uId - id to destroy
  71. Return: none
  72. */
  73. void slapi_uniqueIDDestroy (Slapi_UniqueID **uId)
  74. {
  75. if (uId && *uId)
  76. {
  77. slapi_ch_free ((void**)uId);
  78. *uId = NULL;
  79. }
  80. }
  81. /* Function: slapi_uniqueIDCompare
  82. Description: this function lexically compares two entry ids.
  83. both Ids must have UUID type.
  84. Parameters: uId1, uId2 - ids to compare
  85. Return: -1 if uId1 < uId2
  86. 0 if uId2 == uId2
  87. 1 if uId2 > uId2
  88. UID_BADDATA if invalid pointer passed to the function
  89. */
  90. int slapi_uniqueIDCompare (const Slapi_UniqueID *uId1, const Slapi_UniqueID *uId2){
  91. if (uId1 == NULL || uId2 == NULL)
  92. {
  93. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "uniqueIDCompare: "
  94. "NULL argument passed to the function.\n");
  95. return UID_BADDATA;
  96. }
  97. return(uuid_compare(uId1, uId2));
  98. }
  99. /* Function: slapi_uniqueIDCompareString
  100. Description: this function compares two uniqueids, represented as strings
  101. Parameters: uuid1, uuid2 - ids to compare
  102. Return: 0 if uuid1 == uuid2
  103. non-zero if uuid1 != uuid2 or uuid1 == NULL or uuid2 == NULL
  104. */
  105. int slapi_uniqueIDCompareString(const char *uuid1, const char *uuid2)
  106. {
  107. int return_value = 0; /* assume not equal */
  108. if (NULL != uuid1)
  109. {
  110. if (NULL != uuid2)
  111. {
  112. if (strcmp(uuid1, uuid2) == 0)
  113. {
  114. return_value = 1;
  115. }
  116. }
  117. }
  118. return return_value;
  119. }
  120. /* Function: slapi_uniqueIDFormat
  121. Description: this function converts Slapi_UniqueID to its string representation.
  122. The id format is HHHHHHHH-HHHHHHHH-HHHHHHHH-HHHHHHHH
  123. where H is a hex digit. The data will be outputed in the
  124. network byte order.
  125. Parameters: uId - entry id
  126. buff - buffer in which id is returned; caller must free this
  127. buffer
  128. Return: UID_SUCCESS - function was successfull
  129. UID_BADDATA - invalid parameter passed to the function
  130. UID_MEMORY_ERROR - failed to allocate the buffer
  131. */
  132. int slapi_uniqueIDFormat (const Slapi_UniqueID *uId, char **buff){
  133. guid_t uuid_tmp;
  134. if (uId == NULL || buff == NULL)
  135. {
  136. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "uniqueIDFormat: "
  137. "NULL argument passed to the function.\n");
  138. return UID_BADDATA;
  139. }
  140. *buff = (char*)slapi_ch_malloc (UIDSTR_SIZE + 1);
  141. if (*buff == NULL)
  142. {
  143. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "uniqueIDFormat: "
  144. "failed to allocate buffer.\n");
  145. return UID_MEMORY_ERROR;
  146. }
  147. uuid_tmp = *uId;
  148. uuid_tmp.time_low = htonl(uuid_tmp.time_low);
  149. uuid_tmp.time_mid = htons(uuid_tmp.time_mid);
  150. uuid_tmp.time_hi_and_version = htons(uuid_tmp.time_hi_and_version);
  151. sprintf (*buff, "%2.2x%2.2x%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x-"
  152. "%2.2x%2.2x%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x",
  153. ((PRUint8 *) &uuid_tmp.time_low)[0], ((PRUint8 *) &uuid_tmp.time_low)[1],
  154. ((PRUint8 *) &uuid_tmp.time_low)[2], ((PRUint8 *) &uuid_tmp.time_low)[3],
  155. ((PRUint8 *) &uuid_tmp.time_mid)[0], ((PRUint8 *) &uuid_tmp.time_mid)[1],
  156. ((PRUint8 *) &uuid_tmp.time_hi_and_version)[0],
  157. ((PRUint8 *) &uuid_tmp.time_hi_and_version)[1],
  158. uuid_tmp.clock_seq_hi_and_reserved, uuid_tmp.clock_seq_low,
  159. uuid_tmp.node[0], uuid_tmp.node[1], uuid_tmp.node[2],
  160. uuid_tmp.node[3], uuid_tmp.node[4], uuid_tmp.node[5]);
  161. return UID_SUCCESS;
  162. }
  163. /* Function: slapi_uniqueIDScan
  164. Description: this function converts a string buffer into uniqueID.
  165. Parameters: uId - unique id to be returned
  166. buff - buffer with uniqueID in the format returned by
  167. uniqueIDFormat function
  168. Return: UID_SUCCESS - function was successfull
  169. UID_BADDATA - null parameter(s) or bad format
  170. */
  171. int slapi_uniqueIDScan (Slapi_UniqueID *uId, const char *buff){
  172. if (uId == NULL || buff == NULL)
  173. {
  174. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "uniqueIDScan: "
  175. "NULL argument passed to the function.\n");
  176. return UID_BADDATA;
  177. }
  178. if (!isValidFormat (buff))
  179. {
  180. slapi_log_error (SLAPI_LOG_FATAL, MODULE, "uniqueIDScan: "
  181. "invalid data format.\n");
  182. return UID_BADDATA;
  183. }
  184. ((PRUint8 *) &uId->time_low)[0] = str2Byte (&(buff[0]));
  185. ((PRUint8 *) &uId->time_low)[1] = str2Byte (&(buff[2]));
  186. ((PRUint8 *) &uId->time_low)[2] = str2Byte (&(buff[4]));
  187. ((PRUint8 *) &uId->time_low)[3] = str2Byte (&(buff[6]));
  188. /* next field is at 9 because we skip the - */
  189. ((PRUint8 *) &uId->time_mid)[0] = str2Byte (&(buff[9]));
  190. ((PRUint8 *) &uId->time_mid)[1] = str2Byte (&(buff[11]));
  191. ((PRUint8 *) &uId->time_hi_and_version)[0] = str2Byte (&(buff[13]));
  192. ((PRUint8 *) &uId->time_hi_and_version)[1] = str2Byte (&(buff[15]));
  193. /* next field is at 18 because we skip the - */
  194. uId->clock_seq_hi_and_reserved = str2Byte (&(buff[18]));
  195. uId->clock_seq_low = str2Byte (&(buff[20]));
  196. uId->node[0] = str2Byte (&(buff[22]));
  197. uId->node[1] = str2Byte (&(buff[24]));
  198. /* next field is at 27 because we skip the - */
  199. uId->node[2] = str2Byte (&(buff[27]));
  200. uId->node[3] = str2Byte (&(buff[29]));
  201. uId->node[4] = str2Byte (&(buff[31]));
  202. uId->node[5] = str2Byte (&(buff[33]));
  203. uId->time_low = ntohl(uId->time_low);
  204. uId->time_mid = ntohs(uId->time_mid);
  205. uId->time_hi_and_version = ntohs(uId->time_hi_and_version);
  206. return UID_SUCCESS;
  207. }
  208. /* Function: slapi_uniqueIDIsUUID
  209. Description: tests if given entry id is in UUID format
  210. Parameters: uId - id to test
  211. Return 0 - it is UUID
  212. 1 - it is not UUID
  213. UID_BADDATA - invalid data passed to the function
  214. Note: LPXXX - This call is not used currently. Keep it ???
  215. */
  216. int slapi_uniqueIDIsUUID (const Slapi_UniqueID *uId){
  217. if (uId == NULL)
  218. return UID_BADDATA;
  219. /* Shortening Slapi_UniqueID: This call does nothing */
  220. return (0);
  221. }
  222. /* Name: slapi_uniqueIDSize
  223. Description: returns size of the string version of uniqueID in bytes
  224. Parameters: none
  225. Return: size of the string version of uniqueID in bytes
  226. */
  227. int slapi_uniqueIDSize ()
  228. {
  229. return (UIDSTR_SIZE);
  230. }
  231. /* Name: slapi_uniqueIDDup
  232. Description: duplicates an UniqueID object
  233. Parameters: uId - id to duplicate
  234. Return: duplicate of the Id
  235. */
  236. Slapi_UniqueID* slapi_uniqueIDDup (Slapi_UniqueID *uId)
  237. {
  238. Slapi_UniqueID *uIdDup = slapi_uniqueIDNew ();
  239. memcpy (uIdDup, uId, sizeof (Slapi_UniqueID));
  240. return uIdDup;
  241. }
  242. /* helper functions */
  243. static char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7',
  244. '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', '\0'};
  245. /* this function converts a string representation of a byte in hex into
  246. an actual byte. For instance: "AB" -> 171 */
  247. static PRUint8 str2Byte (const char *str)
  248. {
  249. char letter1 = str[0];
  250. char letter2 = str[1];
  251. PRUint8 num = 0;
  252. int i = 0;
  253. while (hexDigits[i] != '\0')
  254. {
  255. if (letter1 == hexDigits[i] || toupper (letter1) == hexDigits[i])
  256. {
  257. num |= (i << 4);
  258. }
  259. if (letter2 == hexDigits[i] || toupper (letter2) == hexDigits[i])
  260. {
  261. num |= i;
  262. }
  263. i++;
  264. }
  265. return num;
  266. }
  267. static char* format = "XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX";
  268. /* This function verifies that buff contains data in the correct
  269. format (specified above). */
  270. static int isValidFormat (const char * buff)
  271. {
  272. int len;
  273. int i;
  274. if (strlen (buff) != strlen (format))
  275. return UID_BADDATA;
  276. len = strlen (format);
  277. for (i = 0; i < len; i++)
  278. {
  279. if (format[i] == '-' && buff [i] != '-')
  280. return 0;
  281. else if (format[i] == 'X' && ! isxdigit (buff[i]))
  282. return 0;
  283. }
  284. return 1;
  285. }