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

Generated by: LCOV version 1.9