U_CAPI int32_t U_EXPORT2 uidna_toUnicode(const UChar* src, int32_t srcLength, UChar* dest, int32_t destCapacity, int32_t options, UParseError* parseError, UErrorCode* status){ if(status == NULL || U_FAILURE(*status)){ return 0; } if( (src==NULL) || (srcLength < -1) || (destCapacity<0) || (!dest && destCapacity > 0)){ *status = U_ILLEGAL_ARGUMENT_ERROR; return 0; } UStringPrepProfile* nameprep = usprep_openByType(USPREP_RFC3491_NAMEPREP, status); if(U_FAILURE(*status)){ return -1; } int32_t retLen = _internal_toUnicode(src, srcLength, dest, destCapacity, options, nameprep, parseError, status); usprep_close(nameprep); return retLen; }
char * _mongoc_sasl_prep_impl (const char *name, const char *in_utf8, int in_utf8_len, bson_error_t *err) { /* The flow is in_utf8 -> in_utf16 -> SASLPrep -> out_utf16 -> out_utf8. */ UChar *in_utf16, *out_utf16; char *out_utf8; int32_t in_utf16_len, out_utf16_len, out_utf8_len; UErrorCode error_code = U_ZERO_ERROR; UStringPrepProfile *prep; #define SASL_PREP_ERR_RETURN(msg) \ do { \ bson_set_error (err, \ MONGOC_ERROR_SCRAM, \ MONGOC_ERROR_SCRAM_PROTOCOL_ERROR, \ (msg), \ name); \ return NULL; \ } while (0) /* 1. convert str to UTF-16. */ /* preflight to get the destination length. */ (void) u_strFromUTF8 ( NULL, 0, &in_utf16_len, in_utf8, in_utf8_len, &error_code); if (error_code != U_BUFFER_OVERFLOW_ERROR) { SASL_PREP_ERR_RETURN ("could not calculate UTF-16 length of %s"); } /* convert to UTF-16. */ error_code = U_ZERO_ERROR; in_utf16 = bson_malloc (sizeof (UChar) * (in_utf16_len + 1)); /* add one for null byte. */ (void) u_strFromUTF8 ( in_utf16, in_utf16_len + 1, NULL, in_utf8, in_utf8_len, &error_code); if (error_code) { bson_free (in_utf16); SASL_PREP_ERR_RETURN ("could not convert %s to UTF-16"); } /* 2. perform SASLPrep. */ prep = usprep_openByType (USPREP_RFC4013_SASLPREP, &error_code); if (error_code) { bson_free (in_utf16); SASL_PREP_ERR_RETURN ("could not start SASLPrep for %s"); } /* preflight. */ out_utf16_len = usprep_prepare ( prep, in_utf16, in_utf16_len, NULL, 0, USPREP_DEFAULT, NULL, &error_code); if (error_code != U_BUFFER_OVERFLOW_ERROR) { bson_free (in_utf16); usprep_close (prep); SASL_PREP_ERR_RETURN ("could not calculate SASLPrep length of %s"); } /* convert. */ error_code = U_ZERO_ERROR; out_utf16 = bson_malloc (sizeof (UChar) * (out_utf16_len + 1)); (void) usprep_prepare (prep, in_utf16, in_utf16_len, out_utf16, out_utf16_len + 1, USPREP_DEFAULT, NULL, &error_code); if (error_code) { bson_free (in_utf16); bson_free (out_utf16); usprep_close (prep); SASL_PREP_ERR_RETURN ("could not execute SASLPrep for %s"); } bson_free (in_utf16); usprep_close (prep); /* 3. convert back to UTF-8. */ /* preflight. */ (void) u_strToUTF8 ( NULL, 0, &out_utf8_len, out_utf16, out_utf16_len, &error_code); if (error_code != U_BUFFER_OVERFLOW_ERROR) { bson_free (out_utf16); SASL_PREP_ERR_RETURN ("could not calculate UTF-8 length of %s"); } /* convert. */ error_code = U_ZERO_ERROR; out_utf8 = (char *) bson_malloc ( sizeof (char) * (out_utf8_len + 1)); /* add one for null byte. */ (void) u_strToUTF8 ( out_utf8, out_utf8_len + 1, NULL, out_utf16, out_utf16_len, &error_code); if (error_code) { bson_free (out_utf8); bson_free (out_utf16); SASL_PREP_ERR_RETURN ("could not convert %s back to UTF-8"); } bson_free (out_utf16); return out_utf8; #undef SASL_PREP_ERR_RETURN }
U_CAPI int32_t U_EXPORT2 uidna_IDNToUnicode( const UChar* src, int32_t srcLength, UChar* dest, int32_t destCapacity, int32_t options, UParseError* parseError, UErrorCode* status){ if(status == NULL || U_FAILURE(*status)){ return 0; } if((src==NULL) || (srcLength < -1) || (destCapacity<0) || (!dest && destCapacity > 0)){ *status = U_ILLEGAL_ARGUMENT_ERROR; return 0; } int32_t reqLength = 0; UStringPrepProfile* nameprep = usprep_openByType(USPREP_RFC3491_NAMEPREP, status); if(U_FAILURE(*status)){ return 0; } //initialize pointers UChar *delimiter = (UChar*)src; UChar *labelStart = (UChar*)src; UChar *currentDest = (UChar*) dest; int32_t remainingLen = srcLength; int32_t remainingDestCapacity = destCapacity; int32_t labelLen = 0, labelReqLength = 0; UBool done = FALSE; for(;;){ labelLen = getNextSeparator(labelStart,remainingLen, &delimiter,&done); // The RFC states that // <quote> // ToUnicode never fails. If any step fails, then the original input // is returned immediately in that step. // </quote> // _internal_toUnicode will copy the label. /*if(labelLen==0 && done==FALSE){ *status = U_IDNA_ZERO_LENGTH_LABEL_ERROR; break; }*/ labelReqLength = _internal_toUnicode(labelStart, labelLen, currentDest, remainingDestCapacity, options, nameprep, parseError, status); if(*status == U_BUFFER_OVERFLOW_ERROR){ *status = U_ZERO_ERROR; // reset error remainingDestCapacity = 0; } if(U_FAILURE(*status)){ break; } reqLength +=labelReqLength; // adjust the destination pointer if(labelReqLength < remainingDestCapacity){ currentDest = currentDest + labelReqLength; remainingDestCapacity -= labelReqLength; }else{ // should never occur remainingDestCapacity = 0; } if(done == TRUE){ break; } // add the label separator // Unlike the ToASCII operation we don't normalize the label separators if(remainingDestCapacity > 0){ *currentDest++ = *(labelStart + labelLen); remainingDestCapacity--; } reqLength++; labelStart = delimiter; if(remainingLen >0 ){ remainingLen = (int32_t)(srcLength - (delimiter - src)); } } if(reqLength > MAX_DOMAIN_NAME_LENGTH){ *status = U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR; } usprep_close(nameprep); return u_terminateUChars(dest, destCapacity, reqLength, status); }
U_CAPI int32_t U_EXPORT2 uidna_IDNToASCII( const UChar *src, int32_t srcLength, UChar* dest, int32_t destCapacity, int32_t options, UParseError *parseError, UErrorCode *status){ if(status == NULL || U_FAILURE(*status)){ return 0; } if((src==NULL) || (srcLength < -1) || (destCapacity<0) || (!dest && destCapacity > 0)){ *status = U_ILLEGAL_ARGUMENT_ERROR; return 0; } int32_t reqLength = 0; UStringPrepProfile* nameprep = usprep_openByType(USPREP_RFC3491_NAMEPREP, status); if(U_FAILURE(*status)){ return 0; } //initialize pointers UChar *delimiter = (UChar*)src; UChar *labelStart = (UChar*)src; UChar *currentDest = (UChar*) dest; int32_t remainingLen = srcLength; int32_t remainingDestCapacity = destCapacity; int32_t labelLen = 0, labelReqLength = 0; UBool done = FALSE; for(;;){ labelLen = getNextSeparator(labelStart,remainingLen, &delimiter,&done); labelReqLength = 0; if(!(labelLen==0 && done)){// make sure this is not a root label separator. labelReqLength = _internal_toASCII( labelStart, labelLen, currentDest, remainingDestCapacity, options, nameprep, parseError, status); if(*status == U_BUFFER_OVERFLOW_ERROR){ *status = U_ZERO_ERROR; // reset error remainingDestCapacity = 0; } } if(U_FAILURE(*status)){ break; } reqLength +=labelReqLength; // adjust the destination pointer if(labelReqLength < remainingDestCapacity){ currentDest = currentDest + labelReqLength; remainingDestCapacity -= labelReqLength; }else{ // should never occur remainingDestCapacity = 0; } if(done == TRUE){ break; } // add the label separator if(remainingDestCapacity > 0){ *currentDest++ = FULL_STOP; remainingDestCapacity--; } reqLength++; labelStart = delimiter; if(remainingLen >0 ){ remainingLen = (int32_t)(srcLength - (delimiter - src)); } } if(reqLength > MAX_DOMAIN_NAME_LENGTH){ *status = U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR; } usprep_close(nameprep); return u_terminateUChars(dest, destCapacity, reqLength, status); }
extern int testData(TestIDNA& test) { char *basename=NULL; UErrorCode errorCode=U_ZERO_ERROR; char *saveBasename =NULL; profile = usprep_openByType(USPREP_RFC3491_NAMEPREP, &errorCode); if(U_FAILURE(errorCode)){ test.errcheckln(errorCode, "Failed to load IDNA data file. " + UnicodeString(u_errorName(errorCode))); return errorCode; } char* filename = (char*) malloc(strlen(IntlTest::pathToDataDirectory())*1024); //TODO get the srcDir dynamically const char *srcDir=IntlTest::pathToDataDirectory(); idnTrie = &profile->sprepTrie; indexes = profile->indexes; mappingData = profile->mappingData; //initialize pTestIDNA = &test; /* prepare the filename beginning with the source dir */ if(uprv_strchr(srcDir,U_FILE_SEP_CHAR) == NULL){ filename[0] = 0x2E; filename[1] = U_FILE_SEP_CHAR; uprv_strcpy(filename+2,srcDir); }else{ uprv_strcpy(filename, srcDir); } basename=filename+uprv_strlen(filename); if(basename>filename && *(basename-1)!=U_FILE_SEP_CHAR) { *basename++=U_FILE_SEP_CHAR; } /* process unassigned */ basename=filename+uprv_strlen(filename); if(basename>filename && *(basename-1)!=U_FILE_SEP_CHAR) { *basename++=U_FILE_SEP_CHAR; } /* first copy misc directory */ saveBasename = basename; uprv_strcpy(basename,SPREP_DIR); basename = basename + uprv_strlen(SPREP_DIR); *basename++=U_FILE_SEP_CHAR; /* process unassigned */ uprv_strcpy(basename,fileNames[0]); parseMappings(filename,TRUE, test,&errorCode); if(U_FAILURE(errorCode)) { test.errln( "Could not open file %s for reading \n", filename); return errorCode; } testAllCodepoints(test); usprep_close(profile); pTestIDNA = NULL; free(filename); return errorCode; }