LCOV - code coverage report
Current view: directory - netwerk/dns - nameprep.c (source / functions) Found Hit Coverage
Test: app.info Lines: 115 67 58.3 %
Date: 2012-06-02 Functions: 13 7 53.8 %

       1                 : /*
       2                 :  * Copyright (c) 2001,2002 Japan Network Information Center.
       3                 :  * All rights reserved.
       4                 :  *  
       5                 :  * By using this file, you agree to the terms and conditions set forth bellow.
       6                 :  * 
       7                 :  *                      LICENSE TERMS AND CONDITIONS 
       8                 :  * 
       9                 :  * The following License Terms and Conditions apply, unless a different
      10                 :  * license is obtained from Japan Network Information Center ("JPNIC"),
      11                 :  * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
      12                 :  * Chiyoda-ku, Tokyo 101-0047, Japan.
      13                 :  * 
      14                 :  * 1. Use, Modification and Redistribution (including distribution of any
      15                 :  *    modified or derived work) in source and/or binary forms is permitted
      16                 :  *    under this License Terms and Conditions.
      17                 :  * 
      18                 :  * 2. Redistribution of source code must retain the copyright notices as they
      19                 :  *    appear in each source code file, this License Terms and Conditions.
      20                 :  * 
      21                 :  * 3. Redistribution in binary form must reproduce the Copyright Notice,
      22                 :  *    this License Terms and Conditions, in the documentation and/or other
      23                 :  *    materials provided with the distribution.  For the purposes of binary
      24                 :  *    distribution the "Copyright Notice" refers to the following language:
      25                 :  *    "Copyright (c) 2000-2002 Japan Network Information Center.  All rights reserved."
      26                 :  * 
      27                 :  * 4. The name of JPNIC may not be used to endorse or promote products
      28                 :  *    derived from this Software without specific prior written approval of
      29                 :  *    JPNIC.
      30                 :  * 
      31                 :  * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
      32                 :  *    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      33                 :  *    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
      34                 :  *    PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL JPNIC BE LIABLE
      35                 :  *    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      36                 :  *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      37                 :  *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
      38                 :  *    BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
      39                 :  *    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      40                 :  *    OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
      41                 :  *    ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
      42                 :  */
      43                 : 
      44                 : 
      45                 : #include <stdlib.h>
      46                 : #include <string.h>
      47                 : 
      48                 : #include "nsIDNKitInterface.h"
      49                 : 
      50                 : #define UCS_MAX         0x7fffffff
      51                 : #define UNICODE_MAX     0x10ffff
      52                 : 
      53                 : 
      54                 : /*
      55                 :  * Load NAMEPREP compiled tables.
      56                 :  */
      57                 : #include "nameprepdata.c"
      58                 : 
      59                 : /*
      60                 :  * Define mapping/checking functions for each version of the draft.
      61                 :  */
      62                 : 
      63                 : #define VERSION id11
      64                 : #include "nameprep_template.c"
      65                 : #undef VERSION
      66                 : 
      67                 : typedef const char      *(*nameprep_mapproc)(PRUint32 v);
      68                 : typedef int             (*nameprep_checkproc)(PRUint32 v);
      69                 : typedef idn_biditype_t  (*nameprep_biditypeproc)(PRUint32 v);
      70                 : 
      71                 : static struct idn_nameprep {
      72                 :         char *version;
      73                 :         nameprep_mapproc map_proc;
      74                 :         nameprep_checkproc prohibited_proc;
      75                 :         nameprep_checkproc unassigned_proc;
      76                 :         nameprep_biditypeproc biditype_proc;
      77                 : } nameprep_versions[] = {
      78                 : #define MAKE_NAMEPREP_HANDLE(version, id) \
      79                 :         { version, \
      80                 :           compose_sym2(nameprep_map_, id), \
      81                 :           compose_sym2(nameprep_prohibited_, id), \
      82                 :           compose_sym2(nameprep_unassigned_, id), \
      83                 :           compose_sym2(nameprep_biditype_, id), }
      84                 :         MAKE_NAMEPREP_HANDLE("nameprep-11", id11),
      85                 :         { NULL, NULL, NULL, NULL, NULL },
      86                 : };
      87                 : 
      88                 : static idn_result_t     idn_nameprep_check(nameprep_checkproc proc,
      89                 :                                            const PRUint32 *str,
      90                 :                                            const PRUint32 **found);
      91                 : 
      92                 : idn_result_t
      93            1419 : idn_nameprep_create(const char *version, idn_nameprep_t *handlep) {
      94                 :         idn_nameprep_t handle;
      95                 : 
      96                 :         assert(handlep != NULL);
      97                 : 
      98                 :         TRACE(("idn_nameprep_create(version=%-.50s)\n",
      99                 :                version == NULL ? "<NULL>" : version));
     100                 : 
     101            1419 :         if (version == NULL)
     102            1419 :                 version = IDN_NAMEPREP_CURRENT;
     103                 : 
     104                 :         /*
     105                 :          * Lookup table for the specified version.  Since the number of
     106                 :          * versions won't be large (I don't want see draft-23 or such :-),
     107                 :          * simple linear search is OK.
     108                 :          */
     109            1419 :         for (handle = nameprep_versions; handle->version != NULL; handle++) {
     110            1419 :                 if (strcmp(handle->version, version) == 0) {
     111            1419 :                         *handlep = handle;
     112            1419 :                         return (idn_success);
     113                 :                 }
     114                 :         }
     115               0 :         return (idn_notfound);
     116                 : }
     117                 : 
     118                 : void
     119            1416 : idn_nameprep_destroy(idn_nameprep_t handle) {
     120                 :         assert(handle != NULL);
     121                 : 
     122                 :         TRACE(("idn_nameprep_destroy()\n"));
     123                 : 
     124                 :         /* Nothing to do. */
     125            1416 : }
     126                 : 
     127                 : idn_result_t
     128             567 : idn_nameprep_map(idn_nameprep_t handle, const PRUint32 *from,
     129                 :                  PRUint32 *to, size_t tolen) {
     130                 :         assert(handle != NULL && from != NULL && to != NULL);
     131                 : 
     132                 :         TRACE(("idn_nameprep_map(ctx=%s, from=\"%s\")\n",
     133                 :                handle->version, idn__debug_ucs4xstring(from, 50)));
     134                 : 
     135            4598 :         while (*from != '\0') {
     136            3464 :                 PRUint32 v = *from;
     137                 :                 const char *mapped;
     138                 : 
     139            3464 :                 if (v > UCS_MAX) {
     140                 :                         /* This cannot happen, but just in case.. */
     141               0 :                         return (idn_invalid_codepoint);
     142            3464 :                 } else if (v > UNICODE_MAX) {
     143                 :                         /* No mapping is possible. */
     144               0 :                         mapped = NULL;
     145                 :                 } else {
     146                 :                         /* Try mapping. */
     147            3464 :                         mapped = (*handle->map_proc)(v);
     148                 :                 }
     149                 : 
     150            3464 :                 if (mapped == NULL) {
     151                 :                         /* No mapping. Just copy verbatim. */
     152            3464 :                         if (tolen < 1)
     153               0 :                                 return (idn_buffer_overflow);
     154            3464 :                         *to++ = v;
     155            3464 :                         tolen--;
     156                 :                 } else {
     157                 :                         const unsigned char *mappeddata;
     158                 :                         size_t mappedlen;
     159                 : 
     160               0 :                         mappeddata = (const unsigned char *)mapped + 1;
     161               0 :                         mappedlen = *mapped;
     162                 : 
     163               0 :                         if (tolen < (mappedlen + 3) / 4)
     164               0 :                                 return (idn_buffer_overflow);
     165               0 :                         tolen -= (mappedlen + 3) / 4;
     166               0 :                         while (mappedlen >= 4) {
     167               0 :                                 *to  = *mappeddata++;
     168               0 :                                 *to |= *mappeddata++ <<  8;
     169               0 :                                 *to |= *mappeddata++ << 16;
     170               0 :                                 *to |= *mappeddata++ << 24;
     171               0 :                                 mappedlen -= 4;
     172               0 :                                 to++;
     173                 :                         }
     174               0 :                         if (mappedlen > 0) {
     175               0 :                                 *to  = *mappeddata++;
     176               0 :                                 *to |= (mappedlen >= 2) ?
     177               0 :                                        *mappeddata++ <<  8: 0;
     178               0 :                                 *to |= (mappedlen >= 3) ?
     179               0 :                                        *mappeddata++ << 16: 0;
     180               0 :                                 to++;
     181                 :                         }
     182                 :                 }
     183            3464 :                 from++;
     184                 :         }
     185             567 :         if (tolen == 0)
     186               0 :                 return (idn_buffer_overflow);
     187             567 :         *to = '\0';
     188             567 :         return (idn_success);
     189                 : }
     190                 : 
     191                 : idn_result_t
     192             567 : idn_nameprep_isprohibited(idn_nameprep_t handle, const PRUint32 *str,
     193                 :                           const PRUint32 **found) {
     194                 :         assert(handle != NULL && str != NULL && found != NULL);
     195                 : 
     196                 :         TRACE(("idn_nameprep_isprohibited(ctx=%s, str=\"%s\")\n",
     197                 :                handle->version, idn__debug_ucs4xstring(str, 50)));
     198                 : 
     199             567 :         return (idn_nameprep_check(handle->prohibited_proc, str, found));
     200                 : }
     201                 :                 
     202                 : idn_result_t
     203              16 : idn_nameprep_isunassigned(idn_nameprep_t handle, const PRUint32 *str,
     204                 :                           const PRUint32 **found) {
     205                 :         assert(handle != NULL && str != NULL && found != NULL);
     206                 : 
     207                 :         TRACE(("idn_nameprep_isunassigned(handle->version, str=\"%s\")\n",
     208                 :                handle->version, idn__debug_ucs4xstring(str, 50)));
     209                 : 
     210              16 :         return (idn_nameprep_check(handle->unassigned_proc, str, found));
     211                 : }
     212                 :                 
     213                 : static idn_result_t
     214             583 : idn_nameprep_check(nameprep_checkproc proc, const PRUint32 *str,
     215                 :                    const PRUint32 **found) {
     216                 :         PRUint32 v;
     217                 : 
     218            4645 :         while (*str != '\0') {
     219            3497 :                 v = *str;
     220                 : 
     221            3497 :                 if (v > UCS_MAX) {
     222                 :                         /* This cannot happen, but just in case.. */
     223               0 :                         return (idn_invalid_codepoint);
     224            3497 :                 } else if (v > UNICODE_MAX) {
     225                 :                         /* It is invalid.. */
     226               0 :                         *found = str;
     227               0 :                         return (idn_success);
     228            3497 :                 } else if ((*proc)(v)) {
     229              18 :                         *found = str;
     230              18 :                         return (idn_success);
     231                 :                 }
     232            3479 :                 str++;
     233                 :         }
     234             565 :         *found = NULL;
     235             565 :         return (idn_success);
     236                 : }
     237                 : 
     238                 : idn_result_t
     239             552 : idn_nameprep_isvalidbidi(idn_nameprep_t handle, const PRUint32 *str,
     240                 :                          const PRUint32 **found) {
     241                 :         PRUint32 v;
     242                 :         idn_biditype_t first_char;
     243                 :         idn_biditype_t last_char;
     244                 :         int found_r_al;
     245                 : 
     246                 :         assert(handle != NULL && str != NULL && found != NULL);
     247                 : 
     248                 :         TRACE(("idn_nameprep_isvalidbidi(ctx=%s, str=\"%s\")\n",
     249                 :                handle->version, idn__debug_ucs4xstring(str, 50)));
     250                 : 
     251             552 :         if (*str == '\0') {
     252               0 :                 *found = NULL;
     253               0 :                 return (idn_success);
     254                 :         }
     255                 : 
     256                 :         /*
     257                 :          * check first character's type and initialize variables.
     258                 :          */
     259             552 :         found_r_al = 0;
     260             552 :         if (*str > UCS_MAX) {
     261                 :                 /* This cannot happen, but just in case.. */
     262               0 :                 return (idn_invalid_codepoint);
     263             552 :         } else if (*str > UNICODE_MAX) {
     264                 :                 /* It is invalid.. */
     265               0 :                 *found = str;
     266               0 :                 return (idn_success);
     267                 :         }
     268             552 :         first_char = last_char = (*(handle->biditype_proc))(*str);
     269             552 :         if (first_char == idn_biditype_r_al) {
     270              50 :                 found_r_al = 1;
     271                 :         }
     272             552 :         str++;
     273                 : 
     274                 :         /*
     275                 :          * see whether string is valid or not.
     276                 :          */
     277            3904 :         while (*str != '\0') {
     278            2802 :                 v = *str;
     279                 : 
     280            2802 :                 if (v > UCS_MAX) {
     281                 :                         /* This cannot happen, but just in case.. */
     282               0 :                         return (idn_invalid_codepoint);
     283            2802 :                 } else if (v > UNICODE_MAX) {
     284                 :                         /* It is invalid.. */
     285               0 :                         *found = str;
     286               0 :                         return (idn_success);
     287                 :                 } else { 
     288            2802 :                         last_char = (*(handle->biditype_proc))(v);
     289            2802 :                         if (found_r_al && last_char == idn_biditype_l) {
     290               1 :                                 *found = str;
     291               1 :                                 return (idn_success);
     292                 :                         }
     293            2801 :                         if (first_char != idn_biditype_r_al && last_char == idn_biditype_r_al) {
     294               1 :                                 *found = str;
     295               1 :                                 return (idn_success);
     296                 :                         }
     297            2800 :                         if (last_char == idn_biditype_r_al) {
     298             228 :                                 found_r_al = 1;
     299                 :                         }
     300                 :                 }
     301            2800 :                 str++;
     302                 :         }
     303                 : 
     304             550 :         if (found_r_al) {
     305              49 :                 if (last_char != idn_biditype_r_al) {
     306               1 :                         *found = str - 1;
     307               1 :                         return (idn_success);
     308                 :                 }
     309                 :         }
     310                 : 
     311             549 :         *found = NULL;
     312             549 :         return (idn_success);
     313                 : }
     314                 : 
     315                 : idn_result_t
     316               0 : idn_nameprep_createproc(const char *parameter, void **handlep) {
     317               0 :         return idn_nameprep_create(parameter, (idn_nameprep_t *)handlep);
     318                 : }
     319                 : 
     320                 : void
     321               0 : idn_nameprep_destroyproc(void *handle) {
     322               0 :         idn_nameprep_destroy((idn_nameprep_t)handle);
     323               0 : }
     324                 : 
     325                 : idn_result_t
     326               0 : idn_nameprep_mapproc(void *handle, const PRUint32 *from,
     327                 :                       PRUint32 *to, size_t tolen) {
     328               0 :         return idn_nameprep_map((idn_nameprep_t)handle, from, to, tolen);
     329                 : }
     330                 : 
     331                 : idn_result_t
     332               0 : idn_nameprep_prohibitproc(void *handle, const PRUint32 *str,
     333                 :                            const PRUint32 **found) {
     334               0 :         return idn_nameprep_isprohibited((idn_nameprep_t)handle, str, found);
     335                 : }
     336                 : 
     337                 : idn_result_t
     338               0 : idn_nameprep_unassignedproc(void *handle, const PRUint32 *str,
     339                 :                              const PRUint32 **found) {
     340               0 :         return idn_nameprep_isunassigned((idn_nameprep_t)handle, str, found);
     341                 : }
     342                 : 
     343                 : idn_result_t
     344               0 : idn_nameprep_bidiproc(void *handle, const PRUint32 *str,
     345                 :                       const PRUint32 **found) {
     346               0 :         return idn_nameprep_isvalidbidi((idn_nameprep_t)handle, str, found);
     347                 : }

Generated by: LCOV version 1.7