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.
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.
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.
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
34
* END COPYRIGHT BLOCK **/
35
/* ***** BEGIN LICENSE BLOCK *****
37
* The Original Code is Mozilla Communicator client code, released
40
* The Initial Developer of the Original Code is
41
* Netscape Communications Corporation.
42
* Portions created by the Initial Developer are Copyright (C) 1998-1999
43
* the Initial Developer. All Rights Reserved.
47
* Alternatively, the contents of this file may be used under the terms of
48
* either of the GNU General Public License Version 2 or later (the "GPL"),
49
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
50
* in which case the provisions of the GPL or the LGPL are applicable instead
51
* of those above. If you wish to allow use of your version of this file only
52
* under the terms of either the GPL or the LGPL, and not to allow others to
53
* use your version of this file under the terms of the MPL, indicate your
54
* decision by deleting the provisions above and replace them with the notice
55
* and other provisions required by the GPL or the LGPL. If you do not delete
56
* the provisions above, a recipient may use your version of this file under
57
* the terms of any one of the MPL, the GPL or the LGPL.
59
* June 25, 2009 - copied from Mozilla LDAP C SDK - relicensed to use GPLv2
60
* with directory server plug-in exception as per the above paragraph
62
* ***** END LICENSE BLOCK ***** */
64
/* the openldap library has utf8 string handling functions, but they
65
are somewhat different, and not exposed/exported for use outside
66
of the library - therefore, we just copy these from mozldap when
73
#if defined(USE_OPENLDAP)
75
/* uft8.c - misc. utf8 "string" functions. */
76
#include "slapi-plugin.h"
78
static char UTF8len[64]
79
= {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
80
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
81
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
82
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 6};
85
ldap_utf8len (const char* s)
86
/* Return the number of char's in the character at *s. */
88
return ldap_utf8next((char*)s) - s;
92
ldap_utf8next (char* s)
93
/* Return a pointer to the character immediately following *s.
94
Handle any valid UTF-8 character, including '\0' and ASCII.
95
Try to handle a misaligned pointer or a malformed character.
98
register unsigned char* next = (unsigned char*)s;
99
switch (UTF8len [(*next >> 2) & 0x3F]) {
100
case 0: /* erroneous: s points to the middle of a character. */
101
case 6: if ((*++next & 0xC0) != 0x80) break;
102
case 5: if ((*++next & 0xC0) != 0x80) break;
103
case 4: if ((*++next & 0xC0) != 0x80) break;
104
case 3: if ((*++next & 0xC0) != 0x80) break;
105
case 2: if ((*++next & 0xC0) != 0x80) break;
112
ldap_utf8prev (char* s)
113
/* Return a pointer to the character immediately preceding *s.
114
Handle any valid UTF-8 character, including '\0' and ASCII.
115
Try to handle a misaligned pointer or a malformed character.
118
register unsigned char* prev = (unsigned char*)s;
119
unsigned char* limit = prev - 6;
120
while (((*--prev & 0xC0) == 0x80) && (prev != limit)) {
127
ldap_utf8copy (char* dst, const char* src)
128
/* Copy a character from src to dst; return the number of char's copied.
129
Handle any valid UTF-8 character, including '\0' and ASCII.
130
Try to handle a misaligned pointer or a malformed character.
133
register const unsigned char* s = (const unsigned char*)src;
134
switch (UTF8len [(*s >> 2) & 0x3F]) {
135
case 0: /* erroneous: s points to the middle of a character. */
136
case 6: *dst++ = *s++; if ((*s & 0xC0) != 0x80) break;
137
case 5: *dst++ = *s++; if ((*s & 0xC0) != 0x80) break;
138
case 4: *dst++ = *s++; if ((*s & 0xC0) != 0x80) break;
139
case 3: *dst++ = *s++; if ((*s & 0xC0) != 0x80) break;
140
case 2: *dst++ = *s++; if ((*s & 0xC0) != 0x80) break;
143
return s - (const unsigned char*)src;
147
ldap_utf8characters (const char* src)
148
/* Return the number of UTF-8 characters in the 0-terminated array s. */
150
register char* s = (char*)src;
152
for (n = 0; *s; LDAP_UTF8INC(s)) ++n;
157
ldap_utf8getcc( const char** src )
159
register unsigned long c = 0;
160
register const unsigned char* s = (const unsigned char*)*src;
161
switch (UTF8len [(*s >> 2) & 0x3F]) {
162
case 0: /* erroneous: s points to the middle of a character. */
163
c = (*s++) & 0x3F; goto more5;
164
case 1: c = (*s++); break;
165
case 2: c = (*s++) & 0x1F; goto more1;
166
case 3: c = (*s++) & 0x0F; goto more2;
167
case 4: c = (*s++) & 0x07; goto more3;
168
case 5: c = (*s++) & 0x03; goto more4;
169
case 6: c = (*s++) & 0x01; goto more5;
170
more5: if ((*s & 0xC0) != 0x80) break; c = (c << 6) | ((*s++) & 0x3F);
171
more4: if ((*s & 0xC0) != 0x80) break; c = (c << 6) | ((*s++) & 0x3F);
172
more3: if ((*s & 0xC0) != 0x80) break; c = (c << 6) | ((*s++) & 0x3F);
173
more2: if ((*s & 0xC0) != 0x80) break; c = (c << 6) | ((*s++) & 0x3F);
174
more1: if ((*s & 0xC0) != 0x80) break; c = (c << 6) | ((*s++) & 0x3F);
177
*src = (const char*)s;
182
ldap_utf8strtok_r( char* sp, const char* brk, char** next)
185
unsigned long sc, bc;
188
if (sp == NULL && (sp = *next) == NULL)
191
/* Skip leading delimiters; roughly, sp += strspn(sp, brk) */
193
sc = LDAP_UTF8GETC(sp);
194
for (bp = brk; (bc = LDAP_UTF8GETCC(bp)) != 0;) {
199
if (sc == 0) { /* no non-delimiter characters */
203
tok = LDAP_UTF8PREV(sp);
205
/* Scan token; roughly, sp += strcspn(sp, brk)
206
* Note that brk must be 0-terminated; we stop if we see that, too.
209
sc = LDAP_UTF8GETC(sp);
212
if ((bc = LDAP_UTF8GETCC(bp)) == sc) {
217
*(LDAP_UTF8PREV(sp)) = 0;
227
ldap_utf8isalnum( char* s )
229
register unsigned char c = *(unsigned char*)s;
230
if (0x80 & c) return 0;
231
if (c >= 'A' && c <= 'Z') return 1;
232
if (c >= 'a' && c <= 'z') return 1;
233
if (c >= '0' && c <= '9') return 1;
238
ldap_utf8isalpha( char* s )
240
register unsigned char c = *(unsigned char*)s;
241
if (0x80 & c) return 0;
242
if (c >= 'A' && c <= 'Z') return 1;
243
if (c >= 'a' && c <= 'z') return 1;
248
ldap_utf8isdigit( char* s )
250
register unsigned char c = *(unsigned char*)s;
251
if (0x80 & c) return 0;
252
if (c >= '0' && c <= '9') return 1;
257
ldap_utf8isxdigit( char* s )
259
register unsigned char c = *(unsigned char*)s;
260
if (0x80 & c) return 0;
261
if (c >= '0' && c <= '9') return 1;
262
if (c >= 'A' && c <= 'F') return 1;
263
if (c >= 'a' && c <= 'f') return 1;
268
ldap_utf8isspace( char* s )
270
register unsigned char *c = (unsigned char*)s;
271
int len = ldap_utf8len(s);
275
} else if (len == 1) {
287
} else if (len == 2) {
289
return *(c+1) == 0x80;
291
} else if (len == 3) {
296
return (*c>=0x80 && *c<=0x8a);
298
} else if (*c == 0xE3) {
299
return (*(c+1)==0x80) && (*(c+2)==0x80);
300
} else if (*c==0xEF) {
301
return (*(c+1)==0xBB) && (*(c+2)==0xBF);
306
/* should never reach here */
310
#endif /* USE_OPENLDAP */