LCOV - code coverage report
Current view: top level - intl/icu/source/common - uidna.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 368 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 13 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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:  uidna.cpp
      11             :  *   encoding:   UTF-8
      12             :  *   tab size:   8 (not used)
      13             :  *   indentation:4
      14             :  *
      15             :  *   created on: 2003feb1
      16             :  *   created by: Ram Viswanadha
      17             :  */
      18             : 
      19             : #include "unicode/utypes.h"
      20             : 
      21             : #if !UCONFIG_NO_IDNA
      22             : 
      23             : #include "unicode/uidna.h"
      24             : #include "unicode/ustring.h"
      25             : #include "unicode/usprep.h"
      26             : #include "punycode.h"
      27             : #include "ustr_imp.h"
      28             : #include "cmemory.h"
      29             : #include "uassert.h"
      30             : #include "sprpimpl.h"
      31             : 
      32             : /* it is official IDNA ACE Prefix is "xn--" */
      33             : static const UChar ACE_PREFIX[] ={ 0x0078,0x006E,0x002d,0x002d } ;
      34             : #define ACE_PREFIX_LENGTH 4
      35             : 
      36             : #define MAX_LABEL_LENGTH 63
      37             : /* The Max length of the labels should not be more than MAX_LABEL_LENGTH */
      38             : #define MAX_LABEL_BUFFER_SIZE 100
      39             : 
      40             : #define MAX_DOMAIN_NAME_LENGTH 255
      41             : /* The Max length of the domain names should not be more than MAX_DOMAIN_NAME_LENGTH */
      42             : #define MAX_IDN_BUFFER_SIZE   MAX_DOMAIN_NAME_LENGTH+1
      43             : 
      44             : #define LOWER_CASE_DELTA 0x0020
      45             : #define HYPHEN           0x002D
      46             : #define FULL_STOP        0x002E
      47             : #define CAPITAL_A        0x0041
      48             : #define CAPITAL_Z        0x005A
      49             : 
      50             : inline static UChar 
      51           0 : toASCIILower(UChar ch){
      52           0 :     if(CAPITAL_A <= ch && ch <= CAPITAL_Z){
      53           0 :         return ch + LOWER_CASE_DELTA;
      54             :     }
      55           0 :     return ch;
      56             : }
      57             : 
      58             : inline static UBool 
      59           0 : startsWithPrefix(const UChar* src , int32_t srcLength){
      60           0 :     UBool startsWithPrefix = TRUE;
      61             : 
      62           0 :     if(srcLength < ACE_PREFIX_LENGTH){
      63           0 :         return FALSE;
      64             :     }
      65             : 
      66           0 :     for(int8_t i=0; i< ACE_PREFIX_LENGTH; i++){
      67           0 :         if(toASCIILower(src[i]) != ACE_PREFIX[i]){
      68           0 :             startsWithPrefix = FALSE;
      69             :         }
      70             :     }
      71           0 :     return startsWithPrefix;
      72             : }
      73             : 
      74             : 
      75             : inline static int32_t
      76           0 : compareCaseInsensitiveASCII(const UChar* s1, int32_t s1Len, 
      77             :                             const UChar* s2, int32_t s2Len){
      78             :     
      79             :     int32_t minLength;
      80             :     int32_t lengthResult;
      81             : 
      82             :     // are we comparing different lengths?
      83           0 :     if(s1Len != s2Len) {
      84           0 :         if(s1Len < s2Len) {
      85           0 :             minLength = s1Len;
      86           0 :             lengthResult = -1;
      87             :         } else {
      88           0 :             minLength = s2Len;
      89           0 :             lengthResult = 1;
      90             :         }
      91             :     } else {
      92             :         // ok the lengths are equal
      93           0 :         minLength = s1Len;
      94           0 :         lengthResult = 0;
      95             :     }
      96             : 
      97             :     UChar c1,c2;
      98             :     int32_t rc;
      99             : 
     100           0 :     for(int32_t i =0;/* no condition */;i++) {
     101             : 
     102             :         /* If we reach the ends of both strings then they match */
     103           0 :         if(i == minLength) {
     104           0 :             return lengthResult;
     105             :         }
     106             :         
     107           0 :         c1 = s1[i];
     108           0 :         c2 = s2[i];
     109             :         
     110             :         /* Case-insensitive comparison */
     111           0 :         if(c1!=c2) {
     112           0 :             rc=(int32_t)toASCIILower(c1)-(int32_t)toASCIILower(c2);
     113           0 :             if(rc!=0) {
     114           0 :                 lengthResult=rc;
     115           0 :                 break;
     116             :             }
     117             :         }
     118             :     }
     119           0 :     return lengthResult;
     120             : }
     121             : 
     122             : 
     123             : /**
     124             :  * Ascertain if the given code point is a label separator as 
     125             :  * defined by the IDNA RFC
     126             :  * 
     127             :  * @param ch The code point to be ascertained
     128             :  * @return true if the char is a label separator
     129             :  * @stable ICU 2.8
     130             :  */
     131           0 : static inline UBool isLabelSeparator(UChar ch){
     132           0 :     switch(ch){
     133             :         case 0x002e:
     134             :         case 0x3002:
     135             :         case 0xFF0E:
     136             :         case 0xFF61:
     137           0 :             return TRUE;
     138             :         default:
     139           0 :             return FALSE;           
     140             :     }
     141             : }
     142             : 
     143             : // returns the length of the label excluding the separator
     144             : // if *limit == separator then the length returned does not include 
     145             : // the separtor.
     146             : static inline int32_t
     147           0 : getNextSeparator(UChar *src, int32_t srcLength,
     148             :                  UChar **limit, UBool *done){
     149           0 :     if(srcLength == -1){
     150             :         int32_t i;
     151           0 :         for(i=0 ; ;i++){
     152           0 :             if(src[i] == 0){
     153           0 :                 *limit = src + i; // point to null
     154           0 :                 *done = TRUE;
     155           0 :                 return i;
     156             :             }
     157           0 :             if(isLabelSeparator(src[i])){
     158           0 :                 *limit = src + (i+1); // go past the delimiter
     159           0 :                 return i;
     160             :                 
     161             :             }
     162             :         }
     163             :     }else{
     164             :         int32_t i;
     165           0 :         for(i=0;i<srcLength;i++){
     166           0 :             if(isLabelSeparator(src[i])){
     167           0 :                 *limit = src + (i+1); // go past the delimiter
     168           0 :                 return i;
     169             :             }
     170             :         }
     171             :         // we have not found the delimiter
     172             :         // if(i==srcLength)
     173           0 :         *limit = src+srcLength;
     174           0 :         *done = TRUE;
     175             : 
     176           0 :         return i;
     177             :     }
     178             : }
     179           0 : static inline UBool isLDHChar(UChar ch){
     180             :     // high runner case
     181           0 :     if(ch>0x007A){
     182           0 :         return FALSE;
     183             :     }
     184             :     //[\\u002D \\u0030-\\u0039 \\u0041-\\u005A \\u0061-\\u007A]
     185           0 :     if( (ch==0x002D) || 
     186           0 :         (0x0030 <= ch && ch <= 0x0039) ||
     187           0 :         (0x0041 <= ch && ch <= 0x005A) ||
     188           0 :         (0x0061 <= ch && ch <= 0x007A)
     189             :       ){
     190           0 :         return TRUE;
     191             :     }
     192           0 :     return FALSE;
     193             : }
     194             : 
     195             : static int32_t 
     196           0 : _internal_toASCII(const UChar* src, int32_t srcLength, 
     197             :                   UChar* dest, int32_t destCapacity,
     198             :                   int32_t options,
     199             :                   UStringPrepProfile* nameprep,
     200             :                   UParseError* parseError,
     201             :                   UErrorCode* status)
     202             : {
     203             : 
     204             :     // TODO Revisit buffer handling. The label should not be over 63 ASCII characters. ICU4J may need to be updated too.
     205             :     UChar b1Stack[MAX_LABEL_BUFFER_SIZE], b2Stack[MAX_LABEL_BUFFER_SIZE];
     206             :     //initialize pointers to stack buffers
     207           0 :     UChar  *b1 = b1Stack, *b2 = b2Stack;
     208           0 :     int32_t b1Len=0, b2Len, 
     209           0 :             b1Capacity = MAX_LABEL_BUFFER_SIZE, 
     210           0 :             b2Capacity = MAX_LABEL_BUFFER_SIZE ,
     211           0 :             reqLength=0;
     212             : 
     213           0 :     int32_t namePrepOptions = ((options & UIDNA_ALLOW_UNASSIGNED) != 0) ? USPREP_ALLOW_UNASSIGNED: 0;
     214           0 :     UBool* caseFlags = NULL;
     215             :     
     216             :     // the source contains all ascii codepoints
     217           0 :     UBool srcIsASCII  = TRUE;
     218             :     // assume the source contains all LDH codepoints
     219           0 :     UBool srcIsLDH = TRUE; 
     220             : 
     221           0 :     int32_t j=0;
     222             : 
     223             :     //get the options
     224           0 :     UBool useSTD3ASCIIRules = (UBool)((options & UIDNA_USE_STD3_RULES) != 0);
     225             : 
     226           0 :     int32_t failPos = -1;
     227             :     
     228           0 :     if(srcLength == -1){
     229           0 :         srcLength = u_strlen(src);
     230             :     }
     231             :     
     232           0 :     if(srcLength > b1Capacity){
     233           0 :         b1 = (UChar*) uprv_malloc(srcLength * U_SIZEOF_UCHAR);
     234           0 :         if(b1==NULL){
     235           0 :             *status = U_MEMORY_ALLOCATION_ERROR;
     236           0 :             goto CLEANUP;
     237             :         }
     238           0 :         b1Capacity = srcLength;
     239             :     }
     240             : 
     241             :     // step 1 
     242           0 :     for( j=0;j<srcLength;j++){
     243           0 :         if(src[j] > 0x7F){
     244           0 :             srcIsASCII = FALSE;
     245             :         }
     246           0 :         b1[b1Len++] = src[j];
     247             :     }
     248             :     
     249             :     // step 2 is performed only if the source contains non ASCII
     250           0 :     if(srcIsASCII == FALSE){
     251             :         
     252             :         // step 2    
     253           0 :         b1Len = usprep_prepare(nameprep, src, srcLength, b1, b1Capacity, namePrepOptions, parseError, status);
     254             : 
     255           0 :         if(*status == U_BUFFER_OVERFLOW_ERROR){
     256             :             // redo processing of string
     257             :             // we do not have enough room so grow the buffer
     258           0 :             if(b1 != b1Stack){
     259           0 :                 uprv_free(b1);
     260             :             }
     261           0 :             b1 = (UChar*) uprv_malloc(b1Len * U_SIZEOF_UCHAR);
     262           0 :             if(b1==NULL){
     263           0 :                 *status = U_MEMORY_ALLOCATION_ERROR;
     264           0 :                 goto CLEANUP;
     265             :             }
     266             : 
     267           0 :             *status = U_ZERO_ERROR; // reset error
     268             :             
     269           0 :             b1Len = usprep_prepare(nameprep, src, srcLength, b1, b1Len, namePrepOptions, parseError, status);
     270             :         }
     271             :     }
     272             :     // error bail out
     273           0 :     if(U_FAILURE(*status)){
     274           0 :         goto CLEANUP;
     275             :     }
     276           0 :     if(b1Len == 0){
     277           0 :         *status = U_IDNA_ZERO_LENGTH_LABEL_ERROR;
     278           0 :         goto CLEANUP;
     279             :     }
     280             : 
     281             :     // for step 3 & 4
     282           0 :     srcIsASCII = TRUE;
     283           0 :     for( j=0;j<b1Len;j++){
     284             :         // check if output of usprep_prepare is all ASCII 
     285           0 :         if(b1[j] > 0x7F){
     286           0 :             srcIsASCII = FALSE;
     287           0 :         }else if(isLDHChar(b1[j])==FALSE){  // if the char is in ASCII range verify that it is an LDH character
     288           0 :             srcIsLDH = FALSE;
     289           0 :             failPos = j;
     290             :         }
     291             :     }
     292           0 :     if(useSTD3ASCIIRules == TRUE){
     293             :         // verify 3a and 3b
     294             :         // 3(a) Verify the absence of non-LDH ASCII code points; that is, the
     295             :         //  absence of 0..2C, 2E..2F, 3A..40, 5B..60, and 7B..7F.
     296             :         // 3(b) Verify the absence of leading and trailing hyphen-minus; that
     297             :         //  is, the absence of U+002D at the beginning and end of the
     298             :         //  sequence.
     299           0 :         if( srcIsLDH == FALSE /* source at this point should not contain anyLDH characters */
     300           0 :             || b1[0] ==  HYPHEN || b1[b1Len-1] == HYPHEN){
     301           0 :             *status = U_IDNA_STD3_ASCII_RULES_ERROR;
     302             : 
     303             :             /* populate the parseError struct */
     304           0 :             if(srcIsLDH==FALSE){
     305             :                 // failPos is always set the index of failure
     306           0 :                 uprv_syntaxError(b1,failPos, b1Len,parseError);
     307           0 :             }else if(b1[0] == HYPHEN){
     308             :                 // fail position is 0 
     309           0 :                 uprv_syntaxError(b1,0,b1Len,parseError);
     310             :             }else{
     311             :                 // the last index in the source is always length-1
     312           0 :                 uprv_syntaxError(b1, (b1Len>0) ? b1Len-1 : b1Len, b1Len,parseError);
     313             :             }
     314             : 
     315           0 :             goto CLEANUP;
     316             :         }
     317             :     }
     318             :     // Step 4: if the source is ASCII then proceed to step 8
     319           0 :     if(srcIsASCII){
     320           0 :         if(b1Len <= destCapacity){
     321           0 :             u_memmove(dest, b1, b1Len);
     322           0 :             reqLength = b1Len;
     323             :         }else{
     324           0 :             reqLength = b1Len;
     325           0 :             goto CLEANUP;
     326             :         }
     327             :     }else{
     328             :         // step 5 : verify the sequence does not begin with ACE prefix
     329           0 :         if(!startsWithPrefix(b1,b1Len)){
     330             : 
     331             :             //step 6: encode the sequence with punycode
     332             : 
     333             :             // do not preserve the case flags for now!
     334             :             // TODO: Preserve the case while implementing the RFE
     335             :             // caseFlags = (UBool*) uprv_malloc(b1Len * sizeof(UBool));
     336             :             // uprv_memset(caseFlags,TRUE,b1Len);
     337             : 
     338           0 :             b2Len = u_strToPunycode(b1,b1Len,b2,b2Capacity,caseFlags, status);
     339             : 
     340           0 :             if(*status == U_BUFFER_OVERFLOW_ERROR){
     341             :                 // redo processing of string
     342             :                 /* we do not have enough room so grow the buffer*/
     343           0 :                 b2 = (UChar*) uprv_malloc(b2Len * U_SIZEOF_UCHAR); 
     344           0 :                 if(b2 == NULL){
     345           0 :                     *status = U_MEMORY_ALLOCATION_ERROR;
     346           0 :                     goto CLEANUP;
     347             :                 }
     348             : 
     349           0 :                 *status = U_ZERO_ERROR; // reset error
     350             :                 
     351           0 :                 b2Len = u_strToPunycode(b1,b1Len,b2,b2Len,caseFlags, status);
     352             :             }
     353             :             //error bail out
     354           0 :             if(U_FAILURE(*status)){
     355           0 :                 goto CLEANUP;
     356             :             }
     357             :             // TODO : Reconsider while implementing the case preserve RFE
     358             :             // convert all codepoints to lower case ASCII
     359             :             // toASCIILower(b2,b2Len);
     360           0 :             reqLength = b2Len+ACE_PREFIX_LENGTH;
     361             : 
     362           0 :             if(reqLength > destCapacity){
     363           0 :                 *status = U_BUFFER_OVERFLOW_ERROR;
     364           0 :                 goto CLEANUP;
     365             :             }
     366             :             //Step 7: prepend the ACE prefix
     367           0 :             u_memcpy(dest, ACE_PREFIX, ACE_PREFIX_LENGTH);
     368             :             //Step 6: copy the contents in b2 into dest
     369           0 :             u_memcpy(dest+ACE_PREFIX_LENGTH, b2, b2Len);
     370             : 
     371             :         }else{
     372           0 :             *status = U_IDNA_ACE_PREFIX_ERROR; 
     373             :             //position of failure is 0
     374           0 :             uprv_syntaxError(b1,0,b1Len,parseError);
     375           0 :             goto CLEANUP;
     376             :         }
     377             :     }
     378             :     // step 8: verify the length of label
     379           0 :     if(reqLength > MAX_LABEL_LENGTH){
     380           0 :         *status = U_IDNA_LABEL_TOO_LONG_ERROR;
     381             :     }
     382             : 
     383             : CLEANUP:
     384           0 :     if(b1 != b1Stack){
     385           0 :         uprv_free(b1);
     386             :     }
     387           0 :     if(b2 != b2Stack){
     388           0 :         uprv_free(b2);
     389             :     }
     390           0 :     uprv_free(caseFlags);
     391             :     
     392           0 :     return u_terminateUChars(dest, destCapacity, reqLength, status);
     393             : }
     394             : 
     395             : static int32_t
     396           0 : _internal_toUnicode(const UChar* src, int32_t srcLength,
     397             :                     UChar* dest, int32_t destCapacity,
     398             :                     int32_t options,
     399             :                     UStringPrepProfile* nameprep,
     400             :                     UParseError* parseError,
     401             :                     UErrorCode* status)
     402             : {
     403             : 
     404             :     //get the options
     405             :     //UBool useSTD3ASCIIRules = (UBool)((options & UIDNA_USE_STD3_RULES) != 0);
     406           0 :     int32_t namePrepOptions = ((options & UIDNA_ALLOW_UNASSIGNED) != 0) ? USPREP_ALLOW_UNASSIGNED: 0; 
     407             : 
     408             :     // TODO Revisit buffer handling. The label should not be over 63 ASCII characters. ICU4J may need to be updated too.
     409             :     UChar b1Stack[MAX_LABEL_BUFFER_SIZE], b2Stack[MAX_LABEL_BUFFER_SIZE], b3Stack[MAX_LABEL_BUFFER_SIZE];
     410             : 
     411             :     //initialize pointers to stack buffers
     412           0 :     UChar  *b1 = b1Stack, *b2 = b2Stack, *b1Prime=NULL, *b3=b3Stack;
     413           0 :     int32_t b1Len = 0, b2Len, b1PrimeLen, b3Len,
     414           0 :             b1Capacity = MAX_LABEL_BUFFER_SIZE, 
     415           0 :             b2Capacity = MAX_LABEL_BUFFER_SIZE,
     416           0 :             b3Capacity = MAX_LABEL_BUFFER_SIZE,
     417           0 :             reqLength=0;
     418             : 
     419           0 :     UBool* caseFlags = NULL;
     420             : 
     421           0 :     UBool srcIsASCII = TRUE;
     422             :     /*UBool srcIsLDH = TRUE;
     423             :     int32_t failPos =0;*/
     424             : 
     425             :     // step 1: find out if all the codepoints in src are ASCII  
     426           0 :     if(srcLength==-1){
     427           0 :         srcLength = 0;
     428           0 :         for(;src[srcLength]!=0;){
     429           0 :             if(src[srcLength]> 0x7f){
     430           0 :                 srcIsASCII = FALSE;
     431             :             }/*else if(isLDHChar(src[srcLength])==FALSE){
     432             :                 // here we do not assemble surrogates
     433             :                 // since we know that LDH code points
     434             :                 // are in the ASCII range only
     435             :                 srcIsLDH = FALSE;
     436             :                 failPos = srcLength;
     437             :             }*/
     438           0 :             srcLength++;
     439             :         }
     440           0 :     }else if(srcLength > 0){
     441           0 :         for(int32_t j=0; j<srcLength; j++){
     442           0 :             if(src[j]> 0x7f){
     443           0 :                 srcIsASCII = FALSE;
     444             :             }/*else if(isLDHChar(src[j])==FALSE){
     445             :                 // here we do not assemble surrogates
     446             :                 // since we know that LDH code points
     447             :                 // are in the ASCII range only
     448             :                 srcIsLDH = FALSE;
     449             :                 failPos = j;
     450             :             }*/
     451             :         }
     452             :     }else{
     453           0 :         return 0;
     454             :     }
     455             :     
     456           0 :     if(srcIsASCII == FALSE){
     457             :         // step 2: process the string
     458           0 :         b1Len = usprep_prepare(nameprep, src, srcLength, b1, b1Capacity, namePrepOptions, parseError, status);
     459           0 :         if(*status == U_BUFFER_OVERFLOW_ERROR){
     460             :             // redo processing of string
     461             :             /* we do not have enough room so grow the buffer*/
     462           0 :             b1 = (UChar*) uprv_malloc(b1Len * U_SIZEOF_UCHAR);
     463           0 :             if(b1==NULL){
     464           0 :                 *status = U_MEMORY_ALLOCATION_ERROR;
     465           0 :                 goto CLEANUP;
     466             :             }
     467             : 
     468           0 :             *status = U_ZERO_ERROR; // reset error
     469             :             
     470           0 :             b1Len = usprep_prepare(nameprep, src, srcLength, b1, b1Len, namePrepOptions, parseError, status);
     471             :         }
     472             :         //bail out on error
     473           0 :         if(U_FAILURE(*status)){
     474           0 :             goto CLEANUP;
     475             :         }
     476             :     }else{
     477             : 
     478             :         //just point src to b1
     479           0 :         b1 = (UChar*) src;
     480           0 :         b1Len = srcLength;
     481             :     }
     482             : 
     483             :     // The RFC states that 
     484             :     // <quote>
     485             :     // ToUnicode never fails. If any step fails, then the original input
     486             :     // is returned immediately in that step.
     487             :     // </quote>
     488             : 
     489             :     //step 3: verify ACE Prefix
     490           0 :     if(startsWithPrefix(b1,b1Len)){
     491             : 
     492             :         //step 4: Remove the ACE Prefix
     493           0 :         b1Prime = b1 + ACE_PREFIX_LENGTH;
     494           0 :         b1PrimeLen  = b1Len - ACE_PREFIX_LENGTH;
     495             : 
     496             :         //step 5: Decode using punycode
     497           0 :         b2Len = u_strFromPunycode(b1Prime, b1PrimeLen, b2, b2Capacity, caseFlags,status);
     498             : 
     499           0 :         if(*status == U_BUFFER_OVERFLOW_ERROR){
     500             :             // redo processing of string
     501             :             /* we do not have enough room so grow the buffer*/
     502           0 :             b2 = (UChar*) uprv_malloc(b2Len * U_SIZEOF_UCHAR);
     503           0 :             if(b2==NULL){
     504           0 :                 *status = U_MEMORY_ALLOCATION_ERROR;
     505           0 :                 goto CLEANUP;
     506             :             }
     507             : 
     508           0 :             *status = U_ZERO_ERROR; // reset error
     509             : 
     510           0 :             b2Len =  u_strFromPunycode(b1Prime, b1PrimeLen, b2, b2Len, caseFlags, status);
     511             :         }
     512             : 
     513             : 
     514             :         //step 6:Apply toASCII
     515           0 :         b3Len = uidna_toASCII(b2, b2Len, b3, b3Capacity, options, parseError, status);
     516             : 
     517           0 :         if(*status == U_BUFFER_OVERFLOW_ERROR){
     518             :             // redo processing of string
     519             :             /* we do not have enough room so grow the buffer*/
     520           0 :             b3 = (UChar*) uprv_malloc(b3Len * U_SIZEOF_UCHAR);
     521           0 :             if(b3==NULL){
     522           0 :                 *status = U_MEMORY_ALLOCATION_ERROR;
     523           0 :                 goto CLEANUP;
     524             :             }
     525             : 
     526           0 :             *status = U_ZERO_ERROR; // reset error
     527             : 
     528           0 :             b3Len =  uidna_toASCII(b2,b2Len,b3,b3Len,options,parseError, status);
     529             : 
     530             :         }
     531             :         //bail out on error
     532           0 :         if(U_FAILURE(*status)){
     533           0 :             goto CLEANUP;
     534             :         }
     535             : 
     536             :         //step 7: verify
     537           0 :         if(compareCaseInsensitiveASCII(b1, b1Len, b3, b3Len) !=0){
     538             :             // Cause the original to be returned.
     539           0 :             *status = U_IDNA_VERIFICATION_ERROR;
     540           0 :             goto CLEANUP;
     541             :         }
     542             : 
     543             :         //step 8: return output of step 5
     544           0 :         reqLength = b2Len;
     545           0 :         if(b2Len <= destCapacity) {
     546           0 :             u_memmove(dest, b2, b2Len);
     547             :         }
     548             :     }
     549             :     else{
     550             :         // See the start of this if statement for why this is commented out.
     551             :         // verify that STD3 ASCII rules are satisfied
     552             :         /*if(useSTD3ASCIIRules == TRUE){
     553             :             if( srcIsLDH == FALSE // source contains some non-LDH characters
     554             :                 || src[0] ==  HYPHEN || src[srcLength-1] == HYPHEN){
     555             :                 *status = U_IDNA_STD3_ASCII_RULES_ERROR;
     556             : 
     557             :                 // populate the parseError struct
     558             :                 if(srcIsLDH==FALSE){
     559             :                     // failPos is always set the index of failure
     560             :                     uprv_syntaxError(src,failPos, srcLength,parseError);
     561             :                 }else if(src[0] == HYPHEN){
     562             :                     // fail position is 0 
     563             :                     uprv_syntaxError(src,0,srcLength,parseError);
     564             :                 }else{
     565             :                     // the last index in the source is always length-1
     566             :                     uprv_syntaxError(src, (srcLength>0) ? srcLength-1 : srcLength, srcLength,parseError);
     567             :                 }
     568             : 
     569             :                 goto CLEANUP;
     570             :             }
     571             :         }*/
     572             :         // just return the source
     573             :         //copy the source to destination
     574           0 :         if(srcLength <= destCapacity){
     575           0 :             u_memmove(dest, src, srcLength);
     576             :         }
     577           0 :         reqLength = srcLength;
     578             :     }
     579             : 
     580             : 
     581             : CLEANUP:
     582             : 
     583           0 :     if(b1 != b1Stack && b1!=src){
     584           0 :         uprv_free(b1);
     585             :     }
     586           0 :     if(b2 != b2Stack){
     587           0 :         uprv_free(b2);
     588             :     }
     589           0 :     uprv_free(caseFlags);
     590             : 
     591             :     // The RFC states that 
     592             :     // <quote>
     593             :     // ToUnicode never fails. If any step fails, then the original input
     594             :     // is returned immediately in that step.
     595             :     // </quote>
     596             :     // So if any step fails lets copy source to destination
     597           0 :     if(U_FAILURE(*status)){
     598             :         //copy the source to destination
     599           0 :         if(dest && srcLength <= destCapacity){
     600             :             // srcLength should have already been set earlier.
     601           0 :             U_ASSERT(srcLength >= 0);
     602           0 :             u_memmove(dest, src, srcLength);
     603             :         }
     604           0 :         reqLength = srcLength;
     605           0 :         *status = U_ZERO_ERROR;
     606             :     }
     607             : 
     608           0 :     return u_terminateUChars(dest, destCapacity, reqLength, status);
     609             : }
     610             : 
     611             : U_CAPI int32_t U_EXPORT2
     612           0 : uidna_toASCII(const UChar* src, int32_t srcLength, 
     613             :               UChar* dest, int32_t destCapacity,
     614             :               int32_t options,
     615             :               UParseError* parseError,
     616             :               UErrorCode* status){
     617             :     
     618           0 :     if(status == NULL || U_FAILURE(*status)){
     619           0 :         return 0;
     620             :     }
     621           0 :     if((src==NULL) || (srcLength < -1) || (destCapacity<0) || (!dest && destCapacity > 0)){
     622           0 :         *status = U_ILLEGAL_ARGUMENT_ERROR;
     623           0 :         return 0;
     624             :     }
     625             : 
     626           0 :     UStringPrepProfile* nameprep = usprep_openByType(USPREP_RFC3491_NAMEPREP, status);
     627             :     
     628           0 :     if(U_FAILURE(*status)){
     629           0 :         return -1;
     630             :     }
     631             :     
     632           0 :     int32_t retLen = _internal_toASCII(src, srcLength, dest, destCapacity, options, nameprep, parseError, status);
     633             :     
     634             :     /* close the profile*/
     635           0 :     usprep_close(nameprep);
     636             :     
     637           0 :     return retLen;
     638             : }
     639             : 
     640             : U_CAPI int32_t U_EXPORT2
     641           0 : uidna_toUnicode(const UChar* src, int32_t srcLength,
     642             :                 UChar* dest, int32_t destCapacity,
     643             :                 int32_t options,
     644             :                 UParseError* parseError,
     645             :                 UErrorCode* status){
     646             : 
     647           0 :     if(status == NULL || U_FAILURE(*status)){
     648           0 :         return 0;
     649             :     }
     650           0 :     if( (src==NULL) || (srcLength < -1) || (destCapacity<0) || (!dest && destCapacity > 0)){
     651           0 :         *status = U_ILLEGAL_ARGUMENT_ERROR;
     652           0 :         return 0;
     653             :     }  
     654             : 
     655           0 :     UStringPrepProfile* nameprep = usprep_openByType(USPREP_RFC3491_NAMEPREP, status);
     656             :     
     657           0 :     if(U_FAILURE(*status)){
     658           0 :         return -1;
     659             :     }
     660             :     
     661           0 :     int32_t retLen = _internal_toUnicode(src, srcLength, dest, destCapacity, options, nameprep, parseError, status);
     662             : 
     663           0 :     usprep_close(nameprep);
     664             :     
     665           0 :     return retLen;
     666             : }
     667             : 
     668             : 
     669             : U_CAPI int32_t U_EXPORT2
     670           0 : uidna_IDNToASCII(  const UChar *src, int32_t srcLength,
     671             :                    UChar* dest, int32_t destCapacity,
     672             :                    int32_t options,
     673             :                    UParseError *parseError,
     674             :                    UErrorCode *status){
     675             : 
     676           0 :     if(status == NULL || U_FAILURE(*status)){
     677           0 :         return 0;
     678             :     }
     679           0 :     if((src==NULL) || (srcLength < -1) || (destCapacity<0) || (!dest && destCapacity > 0)){
     680           0 :         *status = U_ILLEGAL_ARGUMENT_ERROR;
     681           0 :         return 0;
     682             :     }
     683             : 
     684           0 :     int32_t reqLength = 0;
     685             : 
     686           0 :     UStringPrepProfile* nameprep = usprep_openByType(USPREP_RFC3491_NAMEPREP, status);
     687             :     
     688           0 :     if(U_FAILURE(*status)){
     689           0 :         return 0;
     690             :     }
     691             : 
     692             :     //initialize pointers 
     693           0 :     UChar *delimiter = (UChar*)src;
     694           0 :     UChar *labelStart = (UChar*)src;
     695           0 :     UChar *currentDest = (UChar*) dest;
     696           0 :     int32_t remainingLen = srcLength;
     697           0 :     int32_t remainingDestCapacity = destCapacity;
     698           0 :     int32_t labelLen = 0, labelReqLength = 0;
     699           0 :     UBool done = FALSE;
     700             : 
     701             : 
     702             :     for(;;){
     703             : 
     704           0 :         labelLen = getNextSeparator(labelStart,remainingLen, &delimiter,&done);
     705           0 :         labelReqLength = 0;
     706           0 :         if(!(labelLen==0 && done)){// make sure this is not a root label separator.
     707             :         
     708             :             labelReqLength = _internal_toASCII( labelStart, labelLen, 
     709             :                                                 currentDest, remainingDestCapacity, 
     710             :                                                 options, nameprep, 
     711           0 :                                                 parseError, status);
     712             :     
     713           0 :             if(*status == U_BUFFER_OVERFLOW_ERROR){
     714             :                 
     715           0 :                 *status = U_ZERO_ERROR; // reset error
     716           0 :                 remainingDestCapacity = 0;
     717             :             }
     718             :         }
     719             : 
     720             :     
     721           0 :         if(U_FAILURE(*status)){
     722           0 :             break;
     723             :         }
     724             :         
     725           0 :         reqLength +=labelReqLength;
     726             :         // adjust the destination pointer
     727           0 :         if(labelReqLength < remainingDestCapacity){
     728           0 :             currentDest = currentDest + labelReqLength;
     729           0 :             remainingDestCapacity -= labelReqLength;
     730             :         }else{
     731             :             // should never occur
     732           0 :             remainingDestCapacity = 0;
     733             :         }
     734             : 
     735           0 :         if(done == TRUE){
     736           0 :             break;
     737             :         }
     738             : 
     739             :         // add the label separator
     740           0 :         if(remainingDestCapacity > 0){
     741           0 :             *currentDest++ = FULL_STOP;
     742           0 :             remainingDestCapacity--;
     743             :         }
     744           0 :         reqLength++;
     745             : 
     746           0 :         labelStart = delimiter;
     747           0 :         if(remainingLen >0 ){
     748           0 :             remainingLen = (int32_t)(srcLength - (delimiter - src));
     749             :         }
     750             : 
     751             :     }
     752             : 
     753           0 :     if(reqLength > MAX_DOMAIN_NAME_LENGTH){
     754           0 :         *status = U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR;
     755             :     }
     756             : 
     757           0 :     usprep_close(nameprep);
     758             :     
     759           0 :     return u_terminateUChars(dest, destCapacity, reqLength, status);
     760             : }
     761             : 
     762             : U_CAPI int32_t U_EXPORT2
     763           0 : uidna_IDNToUnicode(  const UChar* src, int32_t srcLength,
     764             :                      UChar* dest, int32_t destCapacity,
     765             :                      int32_t options,
     766             :                      UParseError* parseError,
     767             :                      UErrorCode* status){
     768             :     
     769           0 :     if(status == NULL || U_FAILURE(*status)){
     770           0 :         return 0;
     771             :     }
     772           0 :     if((src==NULL) || (srcLength < -1) || (destCapacity<0) || (!dest && destCapacity > 0)){
     773           0 :         *status = U_ILLEGAL_ARGUMENT_ERROR;
     774           0 :         return 0;
     775             :     }
     776             : 
     777           0 :     int32_t reqLength = 0;
     778             : 
     779           0 :     UStringPrepProfile* nameprep = usprep_openByType(USPREP_RFC3491_NAMEPREP, status);
     780             :     
     781           0 :     if(U_FAILURE(*status)){
     782           0 :         return 0;
     783             :     }
     784             : 
     785             :     //initialize pointers
     786           0 :     UChar *delimiter = (UChar*)src;
     787           0 :     UChar *labelStart = (UChar*)src;
     788           0 :     UChar *currentDest = (UChar*) dest;
     789           0 :     int32_t remainingLen = srcLength;
     790           0 :     int32_t remainingDestCapacity = destCapacity;
     791           0 :     int32_t labelLen = 0, labelReqLength = 0;
     792           0 :     UBool done = FALSE;
     793             : 
     794             :     for(;;){
     795             : 
     796           0 :         labelLen = getNextSeparator(labelStart,remainingLen, &delimiter,&done);
     797             :         
     798             :         // The RFC states that 
     799             :         // <quote>
     800             :         // ToUnicode never fails. If any step fails, then the original input
     801             :         // is returned immediately in that step.
     802             :         // </quote>
     803             :         // _internal_toUnicode will copy the label.
     804             :         /*if(labelLen==0 && done==FALSE){ 
     805             :             *status = U_IDNA_ZERO_LENGTH_LABEL_ERROR;
     806             :             break;
     807             :         }*/
     808             :         
     809             :         labelReqLength = _internal_toUnicode(labelStart, labelLen, 
     810             :                                              currentDest, remainingDestCapacity, 
     811             :                                              options, nameprep, 
     812           0 :                                              parseError, status);
     813             : 
     814           0 :         if(*status == U_BUFFER_OVERFLOW_ERROR){
     815           0 :             *status = U_ZERO_ERROR; // reset error
     816           0 :             remainingDestCapacity = 0;
     817             :         }
     818             : 
     819           0 :         if(U_FAILURE(*status)){
     820           0 :             break;
     821             :         }
     822             :         
     823           0 :         reqLength +=labelReqLength;
     824             :         // adjust the destination pointer
     825           0 :         if(labelReqLength < remainingDestCapacity){
     826           0 :             currentDest = currentDest + labelReqLength;
     827           0 :             remainingDestCapacity -= labelReqLength;
     828             :         }else{
     829             :             // should never occur
     830           0 :             remainingDestCapacity = 0;
     831             :         }
     832             : 
     833           0 :         if(done == TRUE){
     834           0 :             break;
     835             :         }
     836             : 
     837             :         // add the label separator
     838             :         // Unlike the ToASCII operation we don't normalize the label separators
     839           0 :         if(remainingDestCapacity > 0){
     840           0 :             *currentDest++ = *(labelStart + labelLen);
     841           0 :             remainingDestCapacity--;
     842             :         }
     843           0 :         reqLength++;
     844             : 
     845           0 :         labelStart = delimiter;
     846           0 :         if(remainingLen >0 ){
     847           0 :             remainingLen = (int32_t)(srcLength - (delimiter - src));
     848             :         }
     849             : 
     850             :     }
     851             : 
     852           0 :     if(reqLength > MAX_DOMAIN_NAME_LENGTH){
     853           0 :         *status = U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR;
     854             :     }
     855             : 
     856           0 :     usprep_close(nameprep);
     857             :     
     858           0 :     return u_terminateUChars(dest, destCapacity, reqLength, status);
     859             : }
     860             : 
     861             : U_CAPI int32_t U_EXPORT2
     862           0 : uidna_compare(  const UChar *s1, int32_t length1,
     863             :                 const UChar *s2, int32_t length2,
     864             :                 int32_t options,
     865             :                 UErrorCode* status){
     866             : 
     867           0 :     if(status == NULL || U_FAILURE(*status)){
     868           0 :         return -1;
     869             :     }
     870             : 
     871             :     UChar b1Stack[MAX_IDN_BUFFER_SIZE], b2Stack[MAX_IDN_BUFFER_SIZE];
     872           0 :     UChar *b1 = b1Stack, *b2 = b2Stack;
     873           0 :     int32_t b1Len, b2Len, b1Capacity = MAX_IDN_BUFFER_SIZE, b2Capacity = MAX_IDN_BUFFER_SIZE;
     874           0 :     int32_t result=-1;
     875             :     
     876             :     UParseError parseError;
     877             : 
     878           0 :     b1Len = uidna_IDNToASCII(s1, length1, b1, b1Capacity, options, &parseError, status);
     879           0 :     if(*status == U_BUFFER_OVERFLOW_ERROR){
     880             :         // redo processing of string
     881           0 :         b1 = (UChar*) uprv_malloc(b1Len * U_SIZEOF_UCHAR);
     882           0 :         if(b1==NULL){
     883           0 :             *status = U_MEMORY_ALLOCATION_ERROR;
     884           0 :             goto CLEANUP;
     885             :         }
     886             : 
     887           0 :         *status = U_ZERO_ERROR; // reset error
     888             :         
     889           0 :         b1Len = uidna_IDNToASCII(s1,length1,b1,b1Len, options, &parseError, status);
     890             :         
     891             :     }
     892             : 
     893           0 :     b2Len = uidna_IDNToASCII(s2,length2, b2,b2Capacity, options, &parseError, status);
     894           0 :     if(*status == U_BUFFER_OVERFLOW_ERROR){
     895             :         // redo processing of string
     896           0 :         b2 = (UChar*) uprv_malloc(b2Len * U_SIZEOF_UCHAR);
     897           0 :         if(b2==NULL){
     898           0 :             *status = U_MEMORY_ALLOCATION_ERROR;
     899           0 :             goto CLEANUP;
     900             :         }
     901             : 
     902           0 :         *status = U_ZERO_ERROR; // reset error
     903             :         
     904           0 :         b2Len = uidna_IDNToASCII(s2, length2, b2, b2Len, options, &parseError, status);
     905             :         
     906             :     }
     907             :     // when toASCII is applied all label separators are replaced with FULL_STOP
     908           0 :     result = compareCaseInsensitiveASCII(b1,b1Len,b2,b2Len);
     909             : 
     910             : CLEANUP:
     911           0 :     if(b1 != b1Stack){
     912           0 :         uprv_free(b1);
     913             :     }
     914             : 
     915           0 :     if(b2 != b2Stack){
     916           0 :         uprv_free(b2);
     917             :     }
     918             : 
     919           0 :     return result;
     920             : }
     921             : 
     922             : #endif /* #if !UCONFIG_NO_IDNA */

Generated by: LCOV version 1.13