Back to index

lightning-sunbird  0.9+nobinonly
race.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2000,2001,2002 Japan Network Information Center.
00003  * All rights reserved.
00004  *  
00005  * By using this file, you agree to the terms and conditions set forth bellow.
00006  * 
00007  *                   LICENSE TERMS AND CONDITIONS 
00008  * 
00009  * The following License Terms and Conditions apply, unless a different
00010  * license is obtained from Japan Network Information Center ("JPNIC"),
00011  * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
00012  * Chiyoda-ku, Tokyo 101-0047, Japan.
00013  * 
00014  * 1. Use, Modification and Redistribution (including distribution of any
00015  *    modified or derived work) in source and/or binary forms is permitted
00016  *    under this License Terms and Conditions.
00017  * 
00018  * 2. Redistribution of source code must retain the copyright notices as they
00019  *    appear in each source code file, this License Terms and Conditions.
00020  * 
00021  * 3. Redistribution in binary form must reproduce the Copyright Notice,
00022  *    this License Terms and Conditions, in the documentation and/or other
00023  *    materials provided with the distribution.  For the purposes of binary
00024  *    distribution the "Copyright Notice" refers to the following language:
00025  *    "Copyright (c) 2000-2002 Japan Network Information Center.  All rights reserved."
00026  * 
00027  * 4. The name of JPNIC may not be used to endorse or promote products
00028  *    derived from this Software without specific prior written approval of
00029  *    JPNIC.
00030  * 
00031  * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
00032  *    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00033  *    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00034  *    PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL JPNIC BE LIABLE
00035  *    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00036  *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00037  *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
00038  *    BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00039  *    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00040  *    OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
00041  *    ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
00042  */
00043 
00044 
00045 #include <stddef.h>
00046 #include <stdlib.h>
00047 #include <string.h>
00048 
00049 #include "nsIDNKitInterface.h"
00050 
00051 
00052 #define RACE_2OCTET_MODE    0xd8
00053 #define RACE_ESCAPE         0xff
00054 #define RACE_ESCAPE_2ND            0x99
00055 
00056 /*
00057  * Compression type.
00058  */
00059 enum {
00060        compress_one, /* all characters are in a single row */
00061        compress_two, /* row 0 and another row */
00062        compress_none /* nope */
00063 };
00064 
00065 
00066 idn_result_t
00067 race_decode_decompress(const char *from, PRUint16 *buf, size_t buflen)
00068 {
00069        PRUint16 *p = buf;
00070        unsigned int bitbuf = 0;
00071        int bitlen = 0;
00072        unsigned int i, j;
00073        size_t len;
00074 
00075        while (*from != '\0') {
00076               int c = *from++;
00077               int x;
00078 
00079               if ('a' <= c && c <= 'z')
00080                      x = c - 'a';
00081               else if ('A' <= c && c <= 'Z')
00082                      x = c - 'A';
00083               else if ('2' <= c && c <= '7')
00084                      x = c - '2' + 26;
00085               else
00086                      return (idn_invalid_encoding);
00087 
00088               bitbuf = (bitbuf << 5) + x;
00089               bitlen += 5;
00090               if (bitlen >= 8) {
00091                      *p++ = (bitbuf >> (bitlen - 8)) & 0xff;
00092                      bitlen -= 8;
00093               }
00094        }
00095        len = p - buf;
00096 
00097        /*
00098         * Now 'buf' holds the decoded string.
00099         */
00100 
00101        /*
00102         * Decompress.
00103         */
00104        if (buf[0] == RACE_2OCTET_MODE) {
00105               if ((len - 1) % 2 != 0)
00106                      return (idn_invalid_encoding);
00107               for (i = 1, j = 0; i < len; i += 2, j++)
00108                      buf[j] = (buf[i] << 8) + buf[i + 1];
00109               len = j;
00110        } else {
00111               PRUint16 c = buf[0] << 8;   /* higher octet */
00112 
00113               for (i = 1, j = 0; i < len; j++) {
00114                      if (buf[i] == RACE_ESCAPE) {
00115                             if (i + 1 >= len)
00116                                    return (idn_invalid_encoding);
00117                             else if (buf[i + 1] == RACE_ESCAPE_2ND)
00118                                    buf[j] = c | 0xff;
00119                             else
00120                                    buf[j] = buf[i + 1];
00121                             i += 2;
00122 
00123                      } else if (buf[i] == 0x99 && c == 0x00) {
00124                             /*
00125                              * The RACE specification says this is error.
00126                              */
00127                             return (idn_invalid_encoding);
00128                              
00129                      } else {
00130                             buf[j] = c | buf[i++];
00131                      }
00132               }
00133               len = j;
00134        }
00135        buf[len] = '\0';
00136 
00137        return (idn_success);
00138 }
00139 
00140 idn_result_t
00141 race_compress_encode(const PRUint16 *p, int compress_mode,
00142                    char *to, size_t tolen)
00143 {
00144        PRUint32 bitbuf = *p++;     /* bit stream buffer */
00145        int bitlen = 8;                    /* # of bits in 'bitbuf' */
00146 
00147        while (*p != '\0' || bitlen > 0) {
00148               unsigned int c = *p;
00149 
00150               if (c == '\0') {
00151                      /* End of data.  Flush. */
00152                      bitbuf <<= (5 - bitlen);
00153                      bitlen = 5;
00154               } else if (compress_mode == compress_none) {
00155                      /* Push 16 bit data. */
00156                      bitbuf = (bitbuf << 16) | c;
00157                      bitlen += 16;
00158                      p++;
00159               } else {/* compress_mode == compress_one/compress_two */
00160                      /* Push 8 or 16 bit data. */
00161                      if (compress_mode == compress_two &&
00162                          (c & 0xff00) == 0) {
00163                             /* Upper octet is zero (and not U1). */
00164                             bitbuf = (bitbuf << 16) | 0xff00 | c;
00165                             bitlen += 16;
00166                      } else if ((c & 0xff) == 0xff) {
00167                             /* Lower octet is 0xff. */
00168                             bitbuf = (bitbuf << 16) |
00169                                    (RACE_ESCAPE << 8) | RACE_ESCAPE_2ND;
00170                             bitlen += 16;
00171                      } else {
00172                             /* Just output lower octet. */
00173                             bitbuf = (bitbuf << 8) | (c & 0xff);
00174                             bitlen += 8;
00175                      }
00176                      p++;
00177               }
00178 
00179               /*
00180                * Output bits in 'bitbuf' in 5-bit unit.
00181                */
00182               while (bitlen >= 5) {
00183                      int x;
00184 
00185                      /* Get top 5 bits. */
00186                      x = (bitbuf >> (bitlen - 5)) & 0x1f;
00187                      bitlen -= 5;
00188 
00189                      /* Encode. */
00190                      if (x < 26)
00191                             x += 'a';
00192                      else
00193                             x = (x - 26) + '2';
00194 
00195                      if (tolen < 1)
00196                             return (idn_buffer_overflow);
00197 
00198                      *to++ = x;
00199                      tolen--;
00200               }
00201        }
00202 
00203        if (tolen <= 0)
00204               return (idn_buffer_overflow);
00205 
00206        *to = '\0';
00207        return (idn_success);
00208 }
00209 
00210 int
00211 get_compress_mode(PRUint16 *p) {
00212        int zero = 0;
00213        unsigned int upper = 0;
00214        PRUint16 *modepos = p - 1;
00215 
00216        while (*p != '\0') {
00217               unsigned int hi = *p++ & 0xff00;
00218 
00219               if (hi == 0) {
00220                      zero++;
00221               } else if (hi == upper) {
00222                      ;
00223               } else if (upper == 0) {
00224                      upper = hi;
00225               } else {
00226                      *modepos = RACE_2OCTET_MODE;
00227                      return (compress_none);
00228               }
00229        }
00230        *modepos = upper >> 8;
00231        if (upper > 0 && zero > 0)
00232               return (compress_two);
00233        else
00234               return (compress_one);
00235 }