LCOV - code coverage report
Current view: top level - home/jas/src/libidn2 - lookup.c (source / functions) Hit Total Coverage
Test: libidn2 Lines: 53 68 77.9 %
Date: 2011-09-28 Functions: 2 3 66.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 27 36 75.0 %

           Branch data     Line data    Source code
       1                 :            : /* lookup.c - implementation of IDNA2008 lookup functions
       2                 :            :    Copyright (C) 2011 Simon Josefsson
       3                 :            : 
       4                 :            :    This program is free software: you can redistribute it and/or modify
       5                 :            :    it under the terms of the GNU General Public License as published by
       6                 :            :    the Free Software Foundation, either version 3 of the License, or
       7                 :            :    (at your option) any later version.
       8                 :            : 
       9                 :            :    This program is distributed in the hope that it will be useful,
      10                 :            :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      11                 :            :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12                 :            :    GNU General Public License for more details.
      13                 :            : 
      14                 :            :    You should have received a copy of the GNU General Public License
      15                 :            :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      16                 :            : */
      17                 :            : 
      18                 :            : #include <config.h>
      19                 :            : 
      20                 :            : #include "idn2.h"
      21                 :            : 
      22                 :            : #include <errno.h>                /* errno */
      23                 :            : #include <stdlib.h>               /* malloc, free */
      24                 :            : 
      25                 :            : #include "punycode.h"
      26                 :            : 
      27                 :            : #include "uniconv.h"          /* u8_strconv_from_locale */
      28                 :            : #include "uninorm.h"          /* u32_normalize */
      29                 :            : 
      30                 :            : #include "idna.h"             /* _idn2_label_test */
      31                 :            : 
      32                 :            : static int
      33                 :        592 : label (const uint8_t * src, size_t srclen, uint8_t * dst, size_t * dstlen,
      34                 :            :        int flags)
      35                 :            : {
      36                 :            :   size_t plen;
      37                 :            :   uint32_t *p;
      38                 :            :   int rc;
      39                 :            :   size_t tmpl;
      40                 :            : 
      41         [ +  + ]:        592 :   if (_idn2_ascii_p (src, srclen))
      42                 :            :     {
      43         [ -  + ]:        145 :       if (flags & IDN2_ALABEL_ROUNDTRIP)
      44                 :            :         /* FIXME implement this MAY:
      45                 :            : 
      46                 :            :            If the input to this procedure appears to be an A-label
      47                 :            :            (i.e., it starts in "xn--", interpreted
      48                 :            :            case-insensitively), the lookup application MAY attempt to
      49                 :            :            convert it to a U-label, first ensuring that the A-label is
      50                 :            :            entirely in lowercase (converting it to lowercase if
      51                 :            :            necessary), and apply the tests of Section 5.4 and the
      52                 :            :            conversion of Section 5.5 to that form. */
      53                 :          0 :         return -1;
      54                 :            : 
      55         [ +  + ]:        145 :       if (srclen > IDN2_LABEL_MAX_LENGTH)
      56                 :          3 :         return IDN2_TOO_BIG_LABEL;
      57         [ -  + ]:        142 :       if (srclen > *dstlen)
      58                 :          0 :         return IDN2_TOO_BIG_DOMAIN;
      59                 :            : 
      60                 :        142 :       memcpy (dst, src, srclen);
      61                 :        142 :       *dstlen = srclen;
      62                 :        142 :       return IDN2_OK;
      63                 :            :     }
      64                 :            : 
      65                 :        447 :   rc = _idn2_u8_to_u32_nfc (src, srclen, &p, &plen, flags & IDN2_NFC_INPUT);
      66         [ +  + ]:        447 :   if (rc != IDN2_OK)
      67                 :         12 :     return rc;
      68                 :            : 
      69                 :        435 :   rc = _idn2_label_test (TEST_NFC |
      70                 :            :                          TEST_2HYPHEN |
      71                 :            :                          TEST_LEADING_COMBINING |
      72                 :            :                          TEST_DISALLOWED |
      73                 :            :                          TEST_CONTEXTJ_RULE |
      74                 :            :                          TEST_CONTEXTO_WITH_RULE |
      75                 :            :                          TEST_UNASSIGNED | TEST_BIDI, p, plen);
      76         [ +  + ]:        435 :   if (rc != IDN2_OK)
      77                 :            :     {
      78                 :         90 :       free (p);
      79                 :         90 :       return rc;
      80                 :            :     }
      81                 :            : 
      82                 :        345 :   dst[0] = 'x';
      83                 :        345 :   dst[1] = 'n';
      84                 :        345 :   dst[2] = '-';
      85                 :        345 :   dst[3] = '-';
      86                 :            : 
      87                 :        345 :   tmpl = *dstlen - 4;
      88                 :        345 :   rc = _idn2_punycode_encode (plen, p, NULL, &tmpl, (char *) dst + 4);
      89                 :        345 :   free (p);
      90         [ +  + ]:        345 :   if (rc != IDN2_OK)
      91                 :          4 :     return rc;
      92                 :            : 
      93                 :        341 :   *dstlen = 4 + tmpl;
      94                 :            : 
      95                 :        592 :   return IDN2_OK;
      96                 :            : }
      97                 :            : 
      98                 :            : /**
      99                 :            :  * idn2_lookup_u8:
     100                 :            :  * @src: input zero-terminated UTF-8 string in Unicode NFC normalized form.
     101                 :            :  * @lookupname: newly allocated output variable with name to lookup in DNS.
     102                 :            :  * @flags: optional #idn2_flags to modify behaviour.
     103                 :            :  *
     104                 :            :  * Perform IDNA2008 lookup string conversion on domain name @src, as
     105                 :            :  * described in section 5 of RFC 5891.  Note that the input string
     106                 :            :  * must be encoded in UTF-8 and be in Unicode NFC form.
     107                 :            :  *
     108                 :            :  * Pass %IDN2_NFC_INPUT in @flags to convert input to NFC form before
     109                 :            :  * further processing.  Pass %IDN2_ALABEL_ROUNDTRIP in @flags to
     110                 :            :  * convert any input A-labels to U-labels and perform additional
     111                 :            :  * testing.  Multiple flags may be specified by binary or:ing them
     112                 :            :  * together, for example %IDN2_NFC_INPUT | %IDN2_ALABEL_ROUNDTRIP.
     113                 :            :  *
     114                 :            :  * Returns: On successful conversion %IDN2_OK is returned, if the
     115                 :            :  *   output domain or any label would have been too long
     116                 :            :  *   %IDN2_TOO_BIG_DOMAIN or %IDN2_TOO_BIG_LABEL is returned, or
     117                 :            :  *   another error code is returned.
     118                 :            :  **/
     119                 :            : int
     120                 :        458 : idn2_lookup_u8 (const uint8_t * src, uint8_t ** lookupname, int flags)
     121                 :            : {
     122                 :        458 :   size_t lookupnamelen = 0;
     123                 :            :   int rc;
     124                 :            : 
     125         [ -  + ]:        458 :   if (src == NULL)
     126                 :          0 :     return IDN2_OK;
     127                 :            : 
     128                 :        458 :   *lookupname = malloc (IDN2_DOMAIN_MAX_LENGTH + 1);
     129         [ -  + ]:        458 :   if (*lookupname == NULL)
     130                 :          0 :     return IDN2_MALLOC;
     131                 :            : 
     132                 :            :   do
     133                 :            :     {
     134                 :        592 :       const uint8_t *end = strchrnul ((const char *) src, '.');
     135                 :            :       /* XXX Do we care about non-U+002E dots such as U+3002, U+FF0E
     136                 :            :          and U+FF61 here?  Perhaps when IDN2_NFC_INPUT? */
     137                 :        592 :       size_t labellen = end - src;
     138                 :            :       uint8_t tmp[IDN2_LABEL_MAX_LENGTH];
     139                 :        592 :       size_t tmplen = IDN2_LABEL_MAX_LENGTH;
     140                 :            : 
     141                 :        592 :       rc = label (src, labellen, tmp, &tmplen, flags);
     142         [ +  + ]:        592 :       if (rc != IDN2_OK)
     143                 :            :         {
     144                 :        109 :           free (*lookupname);
     145                 :        109 :           return rc;
     146                 :            :         }
     147                 :            : 
     148 [ +  + ][ +  + ]:        483 :       if (lookupnamelen + tmplen
                 [ +  + ]
     149                 :        498 :           > IDN2_DOMAIN_MAX_LENGTH - (tmplen == 0 && *end == '\0' ? 1 : 2))
     150                 :            :         {
     151                 :          2 :           free (*lookupname);
     152                 :          2 :           return IDN2_TOO_BIG_DOMAIN;
     153                 :            :         }
     154                 :            : 
     155                 :        481 :       memcpy (*lookupname + lookupnamelen, tmp, tmplen);
     156                 :        481 :       lookupnamelen += tmplen;
     157                 :            : 
     158         [ +  + ]:        481 :       if (*end == '.')
     159                 :            :         {
     160         [ -  + ]:        134 :           if (lookupnamelen + 1 > IDN2_DOMAIN_MAX_LENGTH)
     161                 :            :             {
     162                 :          0 :               free (*lookupname);
     163                 :          0 :               return IDN2_TOO_BIG_DOMAIN;
     164                 :            :             }
     165                 :            : 
     166                 :        134 :           (*lookupname)[lookupnamelen] = '.';
     167                 :        134 :           lookupnamelen++;
     168                 :            :         }
     169                 :        481 :       (*lookupname)[lookupnamelen] = '\0';
     170                 :            : 
     171                 :        481 :       src = end;
     172                 :            :     }
     173         [ +  + ]:        481 :   while (*src++);
     174                 :            : 
     175                 :        458 :   return IDN2_OK;
     176                 :            : }
     177                 :            : 
     178                 :            : /**
     179                 :            :  * idn2_lookup_ul:
     180                 :            :  * @src: input zero-terminated locale encoded string.
     181                 :            :  * @lookupname: newly allocated output variable with name to lookup in DNS.
     182                 :            :  * @flags: optional #idn2_flags to modify behaviour.
     183                 :            :  *
     184                 :            :  * Perform IDNA2008 lookup string conversion on domain name @src, as
     185                 :            :  * described in section 5 of RFC 5891.  Note that the input is assumed
     186                 :            :  * to be encoded in the locale's default coding system, and will be
     187                 :            :  * transcoded to UTF-8 and NFC normalized by this function.
     188                 :            :  *
     189                 :            :  * Pass %IDN2_ALABEL_ROUNDTRIP in @flags to convert any input A-labels
     190                 :            :  * to U-labels and perform additional testing.
     191                 :            :  *
     192                 :            :  * Returns: On successful conversion %IDN2_OK is returned, if
     193                 :            :  *   conversion from locale to UTF-8 fails then %IDN2_ICONV_FAIL is
     194                 :            :  *   returned, if the output domain or any label would have been too
     195                 :            :  *   long %IDN2_TOO_BIG_DOMAIN or %IDN2_TOO_BIG_LABEL is returned, or
     196                 :            :  *   another error code is returned.
     197                 :            :  **/
     198                 :            : int
     199                 :          0 : idn2_lookup_ul (const char *src, char **lookupname, int flags)
     200                 :            : {
     201                 :          0 :   uint8_t *utf8src = u8_strconv_from_locale (src);
     202                 :            :   int rc;
     203                 :            : 
     204         [ #  # ]:          0 :   if (utf8src == NULL)
     205                 :            :     {
     206         [ #  # ]:          0 :       if (errno == ENOMEM)
     207                 :          0 :         return IDN2_MALLOC;
     208                 :          0 :       return IDN2_ICONV_FAIL;
     209                 :            :     }
     210                 :            : 
     211                 :          0 :   rc = idn2_lookup_u8 (utf8src, (uint8_t **) lookupname,
     212                 :            :                        flags | IDN2_NFC_INPUT);
     213                 :            : 
     214                 :          0 :   free (utf8src);
     215                 :            : 
     216                 :          0 :   return rc;
     217                 :            : }

Generated by: LCOV version 1.8