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 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 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,LENGTHOF(special_prefixes), *prefix, *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 && 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 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 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