1 /*
2 *******************************************************************************
3 *
4 * Copyright (C) 2003-2007, 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
25 #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
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
nfs4_prepare(const char * src,int32_t srcLength,char * dest,int32_t destCapacity,NFS4ProfileState state,UParseError * parseError,UErrorCode * status)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 && destCapacity > 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, parseError, 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, parseError, 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\x0044",
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
findStringIndex(const char * const * sortedArr,int32_t sortedArrLen,const char * target,int32_t targetLen)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
getPrefixSuffix(const char * src,int32_t srcLength,const char ** prefix,int32_t * prefixLen,const char ** suffix,int32_t * suffixLen,UErrorCode * status)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,LENGTHOF(special_prefixes), *prefix, *prefixLen-1) != -1) && (*suffix != NULL)){
199 *status = U_PARSE_ERROR;
200 return;
201 }
202
203 }
204
205 int32_t
nfs4_mixed_prepare(const char * src,int32_t srcLength,char * dest,int32_t destCapacity,UParseError * parseError,UErrorCode * status)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 && destCapacity > 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, status);
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_SUFFIX, 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_SUFFIX, 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
nfs4_cis_prepare(const char * src,int32_t srcLength,char * dest,int32_t destCapacity,UParseError * parseError,UErrorCode * status)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, parseError, status);
285 }
286
287
288 int32_t
nfs4_cs_prepare(const char * src,int32_t srcLength,char * dest,int32_t destCapacity,UBool isCaseSensitive,UParseError * parseError,UErrorCode * status)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
311