OLD | NEW |
| (Empty) |
1 /* | |
2 ******************************************************************************* | |
3 * | |
4 * Copyright (C) 2003-2014, International Business Machines | |
5 * Corporation and others. All Rights Reserved. | |
6 * | |
7 ******************************************************************************* | |
8 * file name: nfsprep.c | |
9 * encoding: US-ASCII | |
10 * tab size: 8 (not used) | |
11 * indentation:4 | |
12 * | |
13 * created on: 2003jul11 | |
14 * created by: Ram Viswanadha | |
15 */ | |
16 | |
17 #include "unicode/utypes.h" | |
18 | |
19 #if !UCONFIG_NO_IDNA | |
20 | |
21 #include "nfsprep.h" | |
22 #include "ustr_imp.h" | |
23 #include "cintltst.h" | |
24 #include "cmemory.h" | |
25 | |
26 #define NFS4_MAX_BUFFER_SIZE 1000 | |
27 #define PREFIX_SUFFIX_SEPARATOR 0x0040 /* '@' */ | |
28 | |
29 | |
30 const char* NFS4DataFileNames[5] ={ | |
31 "nfscss", | |
32 "nfscsi", | |
33 "nfscis", | |
34 "nfsmxp", | |
35 "nfsmxs" | |
36 }; | |
37 | |
38 | |
39 int32_t | |
40 nfs4_prepare( const char* src, int32_t srcLength, | |
41 char* dest, int32_t destCapacity, | |
42 NFS4ProfileState state, | |
43 UParseError* parseError, | |
44 UErrorCode* status){ | |
45 | |
46 UChar b1Stack[NFS4_MAX_BUFFER_SIZE], | |
47 b2Stack[NFS4_MAX_BUFFER_SIZE]; | |
48 char b3Stack[NFS4_MAX_BUFFER_SIZE]; | |
49 | |
50 /* initialize pointers to stack buffers */ | |
51 UChar *b1 = b1Stack, *b2 = b2Stack; | |
52 char *b3=b3Stack; | |
53 int32_t b1Len=0, b2Len=0, b3Len=0, | |
54 b1Capacity = NFS4_MAX_BUFFER_SIZE, | |
55 b2Capacity = NFS4_MAX_BUFFER_SIZE, | |
56 b3Capacity = NFS4_MAX_BUFFER_SIZE, | |
57 reqLength=0; | |
58 | |
59 UStringPrepProfile* profile = NULL; | |
60 /* get the test data path */ | |
61 const char *testdatapath = NULL; | |
62 | |
63 if(status==NULL || U_FAILURE(*status)){ | |
64 return 0; | |
65 } | |
66 if((src==NULL) || (srcLength < -1) || (destCapacity<0) || (!dest && destCapa
city > 0)){ | |
67 *status = U_ILLEGAL_ARGUMENT_ERROR; | |
68 return 0; | |
69 } | |
70 testdatapath = loadTestData(status); | |
71 | |
72 /* convert the string from UTF-8 to UTF-16 */ | |
73 u_strFromUTF8(b1,b1Capacity,&b1Len,src,srcLength,status); | |
74 if(*status == U_BUFFER_OVERFLOW_ERROR){ | |
75 | |
76 /* reset the status */ | |
77 *status = U_ZERO_ERROR; | |
78 | |
79 b1 = (UChar*) malloc(b1Len * U_SIZEOF_UCHAR); | |
80 if(b1==NULL){ | |
81 *status = U_MEMORY_ALLOCATION_ERROR; | |
82 goto CLEANUP; | |
83 } | |
84 | |
85 b1Capacity = b1Len; | |
86 u_strFromUTF8(b1, b1Capacity, &b1Len, src, srcLength, status); | |
87 } | |
88 | |
89 /* open the profile */ | |
90 profile = usprep_open(testdatapath, NFS4DataFileNames[state], status); | |
91 /* prepare the string */ | |
92 b2Len = usprep_prepare(profile, b1, b1Len, b2, b2Capacity, USPREP_DEFAULT, p
arseError, status); | |
93 if(*status == U_BUFFER_OVERFLOW_ERROR){ | |
94 *status = U_ZERO_ERROR; | |
95 b2 = (UChar*) malloc(b2Len * U_SIZEOF_UCHAR); | |
96 if(b2== NULL){ | |
97 *status = U_MEMORY_ALLOCATION_ERROR; | |
98 goto CLEANUP; | |
99 } | |
100 b2Len = usprep_prepare(profile, b1, b1Len, b2, b2Len, USPREP_DEFAULT, pa
rseError, status); | |
101 } | |
102 | |
103 /* convert the string back to UTF-8 */ | |
104 u_strToUTF8(b3,b3Capacity, &b3Len, b2, b2Len, status); | |
105 if(*status == U_BUFFER_OVERFLOW_ERROR){ | |
106 *status = U_ZERO_ERROR; | |
107 b3 = (char*) malloc(b3Len); | |
108 if(b3== NULL){ | |
109 *status = U_MEMORY_ALLOCATION_ERROR; | |
110 goto CLEANUP; | |
111 } | |
112 b3Capacity = b3Len; | |
113 u_strToUTF8(b3,b3Capacity, &b3Len, b2, b2Len, status); | |
114 } | |
115 | |
116 reqLength = b3Len; | |
117 if(dest!=NULL && reqLength <= destCapacity){ | |
118 memmove(dest, b3, reqLength); | |
119 } | |
120 | |
121 CLEANUP: | |
122 if(b1!=b1Stack){ | |
123 free(b1); | |
124 } | |
125 if(b2!=b2Stack){ | |
126 free(b2); | |
127 } | |
128 if(b3!=b3Stack){ | |
129 free(b3); | |
130 } | |
131 | |
132 return u_terminateChars(dest, destCapacity, reqLength, status); | |
133 } | |
134 | |
135 /* sorted array for binary search*/ | |
136 static const char* special_prefixes[]={ | |
137 "\x0041\x004e\x004f\x004e\x0059\x004d\x004f\x0055\x0053", | |
138 "\x0041\x0055\x0054\x0048\x0045\x004e\x0054\x0049\x0043\x0041\x0054\x0045\x0
044", | |
139 "\x0042\x0041\x0054\x0043\x0048", | |
140 "\x0044\x0049\x0041\x004c\x0055\x0050", | |
141 "\x0045\x0056\x0045\x0052\x0059\x004f\x004e\x0045", | |
142 "\x0047\x0052\x004f\x0055\x0050", | |
143 "\x0049\x004e\x0054\x0045\x0052\x0041\x0043\x0054\x0049\x0056\x0045", | |
144 "\x004e\x0045\x0054\x0057\x004f\x0052\x004b", | |
145 "\x004f\x0057\x004e\x0045\x0052", | |
146 }; | |
147 | |
148 | |
149 /* binary search the sorted array */ | |
150 static int | |
151 findStringIndex(const char* const *sortedArr, int32_t sortedArrLen, const char*
target, int32_t targetLen){ | |
152 | |
153 int left, middle, right,rc; | |
154 | |
155 left =0; | |
156 right= sortedArrLen-1; | |
157 | |
158 while(left <= right){ | |
159 middle = (left+right)/2; | |
160 rc=strncmp(sortedArr[middle],target, targetLen); | |
161 | |
162 if(rc<0){ | |
163 left = middle+1; | |
164 }else if(rc >0){ | |
165 right = middle -1; | |
166 }else{ | |
167 return middle; | |
168 } | |
169 } | |
170 return -1; | |
171 } | |
172 | |
173 static void | |
174 getPrefixSuffix(const char *src, int32_t srcLength, | |
175 const char **prefix, int32_t *prefixLen, | |
176 const char **suffix, int32_t *suffixLen, | |
177 UErrorCode *status){ | |
178 | |
179 int32_t i=0; | |
180 *prefix = src; | |
181 while(i<srcLength){ | |
182 if(src[i] == PREFIX_SUFFIX_SEPARATOR){ | |
183 if((i+1) == srcLength){ | |
184 /* we reached the end of the string */ | |
185 *suffix = NULL; | |
186 i++; | |
187 break; | |
188 } | |
189 i++;/* the prefix contains the separator */ | |
190 *suffix = src + i; | |
191 break; | |
192 } | |
193 i++; | |
194 } | |
195 *prefixLen = i; | |
196 *suffixLen = srcLength - i; | |
197 /* special prefixes must not be followed by suffixes! */ | |
198 if((findStringIndex(special_prefixes,UPRV_LENGTHOF(special_prefixes), *prefi
x, *prefixLen-1) != -1) && (*suffix != NULL)){ | |
199 *status = U_PARSE_ERROR; | |
200 return; | |
201 } | |
202 | |
203 } | |
204 | |
205 int32_t | |
206 nfs4_mixed_prepare( const char* src, int32_t srcLength, | |
207 char* dest, int32_t destCapacity, | |
208 UParseError* parseError, | |
209 UErrorCode* status){ | |
210 | |
211 const char *prefix = NULL, *suffix = NULL; | |
212 int32_t prefixLen=0, suffixLen=0; | |
213 char pStack[NFS4_MAX_BUFFER_SIZE], | |
214 sStack[NFS4_MAX_BUFFER_SIZE]; | |
215 char *p=pStack, *s=sStack; | |
216 int32_t pLen=0, sLen=0, reqLen=0, | |
217 pCapacity = NFS4_MAX_BUFFER_SIZE, | |
218 sCapacity = NFS4_MAX_BUFFER_SIZE; | |
219 | |
220 | |
221 if(status==NULL || U_FAILURE(*status)){ | |
222 return 0; | |
223 } | |
224 if((src==NULL) || (srcLength < -1) || (destCapacity<0) || (!dest && destCapa
city > 0)){ | |
225 *status = U_ILLEGAL_ARGUMENT_ERROR; | |
226 return 0; | |
227 } | |
228 if(srcLength == -1){ | |
229 srcLength = (int32_t)strlen(src); | |
230 } | |
231 getPrefixSuffix(src, srcLength, &prefix, &prefixLen, &suffix, &suffixLen, st
atus); | |
232 | |
233 /* prepare the prefix */ | |
234 pLen = nfs4_prepare(prefix, prefixLen, p, pCapacity, NFS4_MIXED_PREP_PREFIX,
parseError, status); | |
235 if(*status == U_BUFFER_OVERFLOW_ERROR){ | |
236 *status = U_ZERO_ERROR; | |
237 p = (char*) malloc(pLen); | |
238 if(p == NULL){ | |
239 *status = U_MEMORY_ALLOCATION_ERROR; | |
240 goto CLEANUP; | |
241 } | |
242 pLen = nfs4_prepare(prefix, prefixLen, p, pLen, NFS4_MIXED_PREP_PREFIX,
parseError, status); | |
243 } | |
244 | |
245 /* prepare the suffix */ | |
246 if(suffix != NULL){ | |
247 sLen = nfs4_prepare(suffix, suffixLen, s, sCapacity, NFS4_MIXED_PREP_SUF
FIX, parseError, status); | |
248 if(*status == U_BUFFER_OVERFLOW_ERROR){ | |
249 *status = U_ZERO_ERROR; | |
250 s = (char*) malloc(pLen); | |
251 if(s == NULL){ | |
252 *status = U_MEMORY_ALLOCATION_ERROR; | |
253 goto CLEANUP; | |
254 } | |
255 sLen = nfs4_prepare(suffix, suffixLen, s, sLen, NFS4_MIXED_PREP_SUFF
IX, parseError, status); | |
256 } | |
257 } | |
258 reqLen = pLen+sLen+1 /* for the delimiter */; | |
259 if(dest != NULL && reqLen <= destCapacity){ | |
260 memmove(dest, p, pLen); | |
261 /* add the suffix */ | |
262 if(suffix!=NULL){ | |
263 dest[pLen++] = PREFIX_SUFFIX_SEPARATOR; | |
264 memmove(dest+pLen, s, sLen); | |
265 } | |
266 } | |
267 | |
268 CLEANUP: | |
269 if(p != pStack){ | |
270 free(p); | |
271 } | |
272 if(s != sStack){ | |
273 free(s); | |
274 } | |
275 | |
276 return u_terminateChars(dest, destCapacity, reqLen, status); | |
277 } | |
278 | |
279 int32_t | |
280 nfs4_cis_prepare( const char* src, int32_t srcLength, | |
281 char* dest, int32_t destCapacity, | |
282 UParseError* parseError, | |
283 UErrorCode* status){ | |
284 return nfs4_prepare(src, srcLength, dest, destCapacity, NFS4_CIS_PREP, parse
Error, status); | |
285 } | |
286 | |
287 | |
288 int32_t | |
289 nfs4_cs_prepare( const char* src, int32_t srcLength, | |
290 char* dest, int32_t destCapacity, | |
291 UBool isCaseSensitive, | |
292 UParseError* parseError, | |
293 UErrorCode* status){ | |
294 if(isCaseSensitive){ | |
295 return nfs4_prepare(src, srcLength, dest, destCapacity, NFS4_CS_PREP_CS,
parseError, status); | |
296 }else{ | |
297 return nfs4_prepare(src, srcLength, dest, destCapacity, NFS4_CS_PREP_CI,
parseError, status); | |
298 } | |
299 } | |
300 | |
301 #endif | |
302 /* | |
303 * Hey, Emacs, please set the following: | |
304 * | |
305 * Local Variables: | |
306 * indent-tabs-mode: nil | |
307 * End: | |
308 * | |
309 */ | |
310 | |
OLD | NEW |