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