value.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  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. /* value.c - routines for dealing with values */
  39. #include <stdio.h>
  40. #include <string.h>
  41. #include <sys/types.h>
  42. #include "syntax.h"
  43. /*
  44. * Do not use the SDK ldap_utf8isspace directly until it is faster
  45. * than this one.
  46. */
  47. static int
  48. utf8isspace_fast( char* s )
  49. {
  50. register unsigned char c = *(unsigned char*)s;
  51. if (0x80 & c) return(ldap_utf8isspace(s));
  52. switch (c) {
  53. case 0x09:
  54. case 0x0A:
  55. case 0x0B:
  56. case 0x0C:
  57. case 0x0D:
  58. case 0x20:
  59. return 1;
  60. default: break;
  61. }
  62. return 0;
  63. }
  64. /*
  65. ** This function is used to normalizes search filter components,
  66. ** and attribute values.
  67. **
  68. ** jcm: I added the trim_spaces flag since this function
  69. ** was incorrectly modifying search filter components. A search
  70. ** of the form "cn=a* b*" (note the space) would be wrongly
  71. ** normalized into "cn=a*b*", because this function is called
  72. ** once for "a" and once for " b".
  73. */
  74. void
  75. value_normalize(
  76. char *s,
  77. int syntax,
  78. int trim_spaces
  79. )
  80. {
  81. char *d;
  82. int prevspace, curspace;
  83. if ( ! (syntax & SYNTAX_CIS) && ! (syntax & SYNTAX_CES) ) {
  84. return;
  85. }
  86. if ( syntax & SYNTAX_DN ) {
  87. (void) slapi_dn_normalize_case( s );
  88. return;
  89. }
  90. d = s;
  91. if (trim_spaces) {
  92. /* strip leading blanks */
  93. while (utf8isspace_fast(s)) {
  94. LDAP_UTF8INC(s);
  95. }
  96. }
  97. /* handle value of all spaces - turn into single space */
  98. /* unless space insensitive syntax - turn into zero length string */
  99. if ( *s == '\0' && s != d ) {
  100. if ( ! (syntax & SYNTAX_SI)) {
  101. *d++ = ' ';
  102. }
  103. *d = '\0';
  104. return;
  105. }
  106. prevspace = 0;
  107. while ( *s ) {
  108. curspace = utf8isspace_fast(s);
  109. /* ignore spaces and '-' in telephone numbers */
  110. if ( (syntax & SYNTAX_TEL) && (curspace || *s == '-') ) {
  111. LDAP_UTF8INC(s);
  112. continue;
  113. }
  114. /* ignore all spaces if this is a space insensitive value */
  115. if ( (syntax & SYNTAX_SI) && curspace ) {
  116. LDAP_UTF8INC(s);
  117. continue;
  118. }
  119. /* compress multiple blanks */
  120. if ( prevspace && curspace ) {
  121. LDAP_UTF8INC(s);
  122. continue;
  123. }
  124. prevspace = curspace;
  125. if ( syntax & SYNTAX_CIS ) {
  126. int ssz, dsz;
  127. slapi_utf8ToLower((unsigned char*)s, (unsigned char *)d, &ssz, &dsz);
  128. s += ssz;
  129. d += dsz;
  130. } else {
  131. char *np;
  132. int sz;
  133. np = ldap_utf8next(s);
  134. if (np == NULL || np == s) break;
  135. sz = np - s;
  136. memmove(d,s,sz);
  137. d += sz;
  138. s += sz;
  139. }
  140. }
  141. *d = '\0';
  142. /* strip trailing blanks */
  143. if (prevspace && trim_spaces) {
  144. char *nd;
  145. nd = ldap_utf8prev(d);
  146. while (nd && utf8isspace_fast(nd)) {
  147. d = nd;
  148. nd = ldap_utf8prev(d);
  149. *d = '\0';
  150. }
  151. }
  152. }
  153. int
  154. value_cmp(
  155. struct berval *v1,
  156. struct berval *v2,
  157. int syntax,
  158. int normalize
  159. )
  160. {
  161. int rc;
  162. struct berval bvcopy1;
  163. struct berval bvcopy2;
  164. char little_buffer[64];
  165. size_t buffer_space = sizeof(little_buffer);
  166. int buffer_offset = 0;
  167. int free_v1 = 0;
  168. int free_v2 = 0;
  169. /* This code used to call malloc up to four times in the copying
  170. * of attributes to be normalized. Now we attempt to keep everything
  171. * on the stack and only malloc if the data is big
  172. */
  173. if ( normalize & 1 ) {
  174. /* Do we have space in the little buffer ? */
  175. if (v1->bv_len < buffer_space) {
  176. bvcopy1.bv_len = v1->bv_len;
  177. SAFEMEMCPY(&little_buffer[buffer_offset],v1->bv_val,v1->bv_len);
  178. bvcopy1.bv_val = &little_buffer[buffer_offset];
  179. bvcopy1.bv_val[v1->bv_len] = '\0';
  180. v1 = &bvcopy1;
  181. buffer_space-= v1->bv_len+1;
  182. buffer_offset+= v1->bv_len+1;
  183. } else {
  184. v1 = ber_bvdup( v1 );
  185. free_v1 = 1;
  186. }
  187. value_normalize( v1->bv_val, syntax, 1 /* trim leading blanks */ );
  188. }
  189. if ( normalize & 2 ) {
  190. /* Do we have space in the little buffer ? */
  191. if (v2->bv_len < buffer_space) {
  192. bvcopy2.bv_len = v2->bv_len;
  193. SAFEMEMCPY(&little_buffer[buffer_offset],v2->bv_val,v2->bv_len);
  194. bvcopy2.bv_val = &little_buffer[buffer_offset];
  195. bvcopy2.bv_val[v2->bv_len] = '\0';
  196. v2 = &bvcopy2;
  197. buffer_space-= v2->bv_len+1;
  198. buffer_offset+= v2->bv_len+1;
  199. } else {
  200. v2 = ber_bvdup( v2 );
  201. free_v2 = 1;
  202. }
  203. value_normalize( v2->bv_val, syntax, 1 /* trim leading blanks */ );
  204. }
  205. switch ( syntax ) {
  206. case SYNTAX_CIS:
  207. case (SYNTAX_CIS | SYNTAX_TEL):
  208. case (SYNTAX_CIS | SYNTAX_DN):
  209. case (SYNTAX_CIS | SYNTAX_SI):
  210. rc = slapi_utf8casecmp( (unsigned char *)v1->bv_val,
  211. (unsigned char *)v2->bv_val );
  212. break;
  213. case SYNTAX_CES:
  214. rc = strcmp( v1->bv_val, v2->bv_val );
  215. break;
  216. }
  217. if ( (normalize & 1) && free_v1) {
  218. ber_bvfree( v1 );
  219. }
  220. if ( (normalize & 2) && free_v2) {
  221. ber_bvfree( v2 );
  222. }
  223. return( rc );
  224. }