• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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