~ubuntu-branches/ubuntu/wily/389-ds-base/wily

« back to all changes in this revision

Viewing changes to ldap/servers/slapd/utf8.c

  • Committer: Package Import Robot
  • Author(s): Krzysztof Klimonda
  • Date: 2012-03-27 14:26:16 UTC
  • Revision ID: package-import@ubuntu.com-20120327142616-xt24t6nffm3f7ybz
Tags: upstream-1.2.11.7
ImportĀ upstreamĀ versionĀ 1.2.11.7

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 * END COPYRIGHT BLOCK **/
 
35
/* ***** BEGIN LICENSE BLOCK *****
 
36
 * 
 
37
 * The Original Code is Mozilla Communicator client code, released
 
38
 * March 31, 1998.
 
39
 * 
 
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.
 
44
 * 
 
45
 * Contributor(s):
 
46
 * 
 
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.
 
58
 *
 
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
 
61
 * 
 
62
 * ***** END LICENSE BLOCK ***** */
 
63
 
 
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
 
67
   using openldap
 
68
*/
 
69
#ifdef HAVE_CONFIG_H
 
70
#  include <config.h>
 
71
#endif
 
72
 
 
73
#if defined(USE_OPENLDAP)
 
74
 
 
75
/* uft8.c - misc. utf8 "string" functions. */
 
76
#include "slapi-plugin.h"
 
77
 
 
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};
 
83
 
 
84
int
 
85
ldap_utf8len (const char* s)
 
86
     /* Return the number of char's in the character at *s. */
 
87
{
 
88
    return ldap_utf8next((char*)s) - s;
 
89
}
 
90
 
 
91
char*
 
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.
 
96
     */
 
97
{
 
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;
 
106
      case 1: ++next;
 
107
    }
 
108
    return (char*) next;
 
109
}
 
110
 
 
111
char*
 
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.
 
116
     */
 
117
{
 
118
    register unsigned char* prev = (unsigned char*)s;
 
119
    unsigned char* limit = prev - 6;
 
120
    while (((*--prev & 0xC0) == 0x80) && (prev != limit)) {
 
121
        ;
 
122
    }
 
123
    return (char*) prev;
 
124
}
 
125
 
 
126
int
 
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.
 
131
     */
 
132
{
 
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;
 
141
      case 1: *dst   = *s++;
 
142
    }
 
143
    return s - (const unsigned char*)src;
 
144
}
 
145
 
 
146
size_t
 
147
ldap_utf8characters (const char* src)
 
148
     /* Return the number of UTF-8 characters in the 0-terminated array s. */
 
149
{
 
150
    register char* s = (char*)src;
 
151
    size_t n;
 
152
    for (n = 0; *s; LDAP_UTF8INC(s)) ++n;
 
153
    return n;
 
154
}
 
155
 
 
156
unsigned long
 
157
ldap_utf8getcc( const char** src )
 
158
{
 
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);
 
175
        break;
 
176
    }
 
177
    *src = (const char*)s;
 
178
    return c;
 
179
}
 
180
 
 
181
char*
 
182
ldap_utf8strtok_r( char* sp, const char* brk, char** next)
 
183
{
 
184
    const char *bp;
 
185
    unsigned long sc, bc;
 
186
    char *tok;
 
187
 
 
188
    if (sp == NULL && (sp = *next) == NULL)
 
189
      return NULL;
 
190
 
 
191
    /* Skip leading delimiters; roughly, sp += strspn(sp, brk) */
 
192
  cont:
 
193
    sc = LDAP_UTF8GETC(sp);
 
194
    for (bp = brk; (bc = LDAP_UTF8GETCC(bp)) != 0;) {
 
195
        if (sc == bc)
 
196
          goto cont;
 
197
    }
 
198
 
 
199
    if (sc == 0) { /* no non-delimiter characters */
 
200
        *next = NULL;
 
201
        return NULL;
 
202
    }
 
203
    tok = LDAP_UTF8PREV(sp);
 
204
 
 
205
    /* Scan token; roughly, sp += strcspn(sp, brk)
 
206
     * Note that brk must be 0-terminated; we stop if we see that, too.
 
207
     */
 
208
    while (1) {
 
209
        sc = LDAP_UTF8GETC(sp);
 
210
        bp = brk;
 
211
        do {
 
212
            if ((bc = LDAP_UTF8GETCC(bp)) == sc) {
 
213
                if (sc == 0) {
 
214
                    *next = NULL;
 
215
                } else {
 
216
                    *next = sp;
 
217
                    *(LDAP_UTF8PREV(sp)) = 0;
 
218
                }
 
219
                return tok;
 
220
            }
 
221
        } while (bc != 0);
 
222
    }
 
223
    /* NOTREACHED */
 
224
}
 
225
 
 
226
int
 
227
ldap_utf8isalnum( char* s )
 
228
{
 
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;
 
234
    return 0;
 
235
}
 
236
 
 
237
int
 
238
ldap_utf8isalpha( char* s )
 
239
{
 
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;
 
244
    return 0;
 
245
}
 
246
 
 
247
int
 
248
ldap_utf8isdigit( char* s )
 
249
{
 
250
    register unsigned char c = *(unsigned char*)s;
 
251
    if (0x80 & c) return 0;
 
252
    if (c >= '0' && c <= '9') return 1;
 
253
    return 0;
 
254
}
 
255
 
 
256
int
 
257
ldap_utf8isxdigit( char* s )
 
258
{
 
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;
 
264
    return 0;
 
265
}
 
266
 
 
267
int
 
268
ldap_utf8isspace( char* s )
 
269
{
 
270
    register unsigned char *c = (unsigned char*)s;
 
271
    int len = ldap_utf8len(s);
 
272
 
 
273
    if (len == 0) {
 
274
        return 0;
 
275
    } else if (len == 1) {
 
276
        switch (*c) {
 
277
            case 0x09:
 
278
            case 0x0A:
 
279
            case 0x0B:
 
280
            case 0x0C:
 
281
            case 0x0D:
 
282
            case 0x20:
 
283
                return 1;
 
284
            default:
 
285
                return 0;
 
286
        }
 
287
    } else if (len == 2) {
 
288
        if (*c == 0xc2) {
 
289
                return *(c+1) == 0x80;
 
290
        }
 
291
    } else if (len == 3) {
 
292
        if (*c == 0xE2) {
 
293
            c++;
 
294
            if (*c == 0x80) {
 
295
                c++;
 
296
                return (*c>=0x80 && *c<=0x8a);
 
297
            }
 
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);
 
302
        }
 
303
        return 0;
 
304
    }
 
305
 
 
306
    /* should never reach here */
 
307
    return 0;
 
308
}
 
309
 
 
310
#endif /* USE_OPENLDAP */