lace.c revision 04bdb234571448ed6194e1d4048e6512f2446f1c
75b02323f467087cf9ccd3acb95da902d6be1cf4Bob Halleystatic char *rcsid = "$Id: lace.c,v 1.4 2000/11/22 01:52:18 ishisone Exp $";
75b02323f467087cf9ccd3acb95da902d6be1cf4Bob Halley * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
75b02323f467087cf9ccd3acb95da902d6be1cf4Bob Halley * By using this file, you agree to the terms and conditions set forth bellow.
75b02323f467087cf9ccd3acb95da902d6be1cf4Bob Halley * LICENSE TERMS AND CONDITIONS
75b02323f467087cf9ccd3acb95da902d6be1cf4Bob Halley * The following License Terms and Conditions apply, unless a different
75b02323f467087cf9ccd3acb95da902d6be1cf4Bob Halley * license is obtained from Japan Network Information Center ("JPNIC"),
75b02323f467087cf9ccd3acb95da902d6be1cf4Bob Halley * a Japanese association, Fuundo Bldg., 1-2 Kanda Ogawamachi, Chiyoda-ku,
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * Tokyo, Japan.
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson * 1. Use, Modification and Redistribution (including distribution of any
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley * modified or derived work) in source and/or binary forms is permitted
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley * under this License Terms and Conditions.
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley * 2. Redistribution of source code must retain the copyright notices as they
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley * appear in each source code file, this License Terms and Conditions.
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley * 3. Redistribution in binary form must reproduce the Copyright Notice,
ccdac53c027e8964753b36c4d8c7b0e98af501c2Michael Graff * this License Terms and Conditions, in the documentation and/or other
ccdac53c027e8964753b36c4d8c7b0e98af501c2Michael Graff * materials provided with the distribution. For the purposes of binary
ccdac53c027e8964753b36c4d8c7b0e98af501c2Michael Graff * distribution the "Copyright Notice" refers to the following language:
ccdac53c027e8964753b36c4d8c7b0e98af501c2Michael Graff * "Copyright (c) Japan Network Information Center. All rights reserved."
ccdac53c027e8964753b36c4d8c7b0e98af501c2Michael Graff * 4. Neither the name of JPNIC may be used to endorse or promote products
ccdac53c027e8964753b36c4d8c7b0e98af501c2Michael Graff * derived from this Software without specific prior written approval of
75a4dd0d377dca2f85cea44e28bf110314c1fe8cDavid Lawrence * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
75a4dd0d377dca2f85cea44e28bf110314c1fe8cDavid Lawrence * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
75a4dd0d377dca2f85cea44e28bf110314c1fe8cDavid Lawrence * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
75a4dd0d377dca2f85cea44e28bf110314c1fe8cDavid Lawrence * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
8e06cea14c857429ab7e7299af2dce5eeeaa5ff0Michael Graff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
8e06cea14c857429ab7e7299af2dce5eeeaa5ff0Michael Graff * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
8e06cea14c857429ab7e7299af2dce5eeeaa5ff0Michael Graff * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * 6. Indemnification by Licensee
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * Any person or entities using and/or redistributing this Software under
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * this License Terms and Conditions shall defend indemnify and hold
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * harmless JPNIC from and against any and all judgements damages,
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * expenses, settlement liabilities, cost and other liabilities of any
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * kind as a result of use and redistribution of this Software or any
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * claim, suite, action, litigation or proceeding by any third party
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * arising out of or relates to this License Terms and Conditions.
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * 7. Governing Law, Jurisdiction and Venue
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * This License Terms and Conditions shall be governed by and and
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * construed in accordance with the law of Japan. Any person or entities
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * using and/or redistributing this Software under this License Terms and
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * Conditions hereby agrees and consent to the personal and exclusive
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * jurisdiction and venue of Tokyo District Court of Japan.
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence/* Be paranoid. */
0293ad13207aa29bd5844cdc87d085ffc009d749David Lawrence#define LACE_PREFIX_LEN (strlen(MDN_LACE_PREFIX))
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence#define LACE_BUF_SIZE 128 /* more than enough */
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrencestatic mdn_result_t lace_l2u(const char *from, const char *end,
0293ad13207aa29bd5844cdc87d085ffc009d749David Lawrencestatic mdn_result_t lace_u2l(const char *from, const char *end,
0293ad13207aa29bd5844cdc87d085ffc009d749David Lawrencestatic mdn_result_t lace_decode(const char *from, size_t fromlen,
0293ad13207aa29bd5844cdc87d085ffc009d749David Lawrencestatic mdn_result_t lace_decode_utf16(const char *from, size_t fromlen,
0293ad13207aa29bd5844cdc87d085ffc009d749David Lawrencestatic mdn_result_t lace_encode(const char *from, size_t fromlen,
0293ad13207aa29bd5844cdc87d085ffc009d749David Lawrencestatic mdn_result_t lace_encode_utf16(const unsigned short *p,
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrencestatic int is_compress_effective(unsigned short *p, size_t len);
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence/* ARGSUSED */
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrencemdn__lace_open(mdn_converter_t ctx, mdn_converter_dir_t dir) {
657ce0b9d84fbd66514df53d61a087e8f1161187Michael Graff/* ARGSUSED */
657ce0b9d84fbd66514df53d61a087e8f1161187Michael Graffmdn__lace_close(mdn_converter_t ctx, mdn_converter_dir_t dir) {
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrencemdn__lace_convert(mdn_converter_t ctx, mdn_converter_dir_t dir,
4bcaefbcd3ced942139fdc830e007c6ea2b8d2feDavid Lawrence (dir == mdn_converter_l2u || dir == mdn_converter_u2l));
4bcaefbcd3ced942139fdc830e007c6ea2b8d2feDavid Lawrence TRACE(("mdn__lace_convert(dir=%s,from=\"%s\")\n",
4bcaefbcd3ced942139fdc830e007c6ea2b8d2feDavid Lawrence * Find the end of this component (label).
657ce0b9d84fbd66514df53d61a087e8f1161187Michael Graff * Convert it.
e915367e40b579d18ac13c9c58c15fec614d9890Michael Graff * Copy '.' or NUL.
08a768e82ad64ede97f640c88e02984b59122753Michael Graff DUMP(("mdn__lace_convert: \"%s\"\n", mdn_debug_xstring(toorg, 70)));
08a768e82ad64ede97f640c88e02984b59122753Michael Graff mdn_util_casematch(from, MDN_LACE_PREFIX, prefix_len)) {
08a768e82ad64ede97f640c88e02984b59122753Michael Graff * LACE encoding prefix found.
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence * Not LACE encoded. Copy verbatim.
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson if (mdn_util_domainspan(from, end) < end) {
8a9b755d32a4f6ace792ac3fd17c968cf96d2487David Lawrence /* invalid character found */
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafssonlace_u2l(const char *from, const char *end,
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson * See if encoding is necessary.
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson if (mdn_util_domainspan(from, end) < end) {
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson * Conversion is necessary.
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson /* Set prefix. */
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson (void)memcpy(to, MDN_LACE_PREFIX, prefix_len);
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson * Conversion is NOT necessary.
ea31416b4fcdf23732355a8002f93f29e3b3d2dbAndreas Gustafsson * Copy verbatim.
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halleylace_decode(const char *from, size_t fromlen, char *to, size_t tolen) {
7bb707a34778fc4bd9624d6c5de95675424ea59fDavid Lawrence unsigned short *buf;
7b2db4b8d13e3d8bc81419ffcc8b39de8193ef63David Lawrence * Allocate sufficient buffer.
7b2db4b8d13e3d8bc81419ffcc8b39de8193ef63David Lawrence if ((buf = malloc(sizeof(*buf) * fromlen)) == NULL)
35c842e05dc6382ce1d9161a658d3ff4b2c3d4c9Bob Halley /* Use local buffer. */
c195f74e092cb8a29f144c8e81012bd9c61a79a2Michael Graff * Decode base32 and decompress.
bba4edf671cc3f0d5b0d3eabfaf28d96aadf23ffDavid Lawrence r = lace_decode_utf16(from, fromlen, buf, &len);
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley * Now 'buf' holds the decompressed string, which must contain
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley * UTF-16 characters. Convert them into UTF-8.
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley r = mdn_util_utf16toutf8(buf, len, to, tolen, &reslen);
a2171e092382f8f8a72b1f73436ddf93918c7719Bob Halley * Terminate with NUL.
a505a3f6e09218bebac020fc49105b2e6cd9e25cBob Halleylace_decode_utf16(const char *from, size_t fromlen,
566a01eb745d49bd866971062388cd11d525b60dDavid Lawrence unsigned short *p, *q;
566a01eb745d49bd866971062388cd11d525b60dDavid Lawrence unsigned int bitbuf = 0;
566a01eb745d49bd866971062388cd11d525b60dDavid Lawrence * Decode Base32 and put the result bytes to 'buf'.
566a01eb745d49bd866971062388cd11d525b60dDavid Lawrence * Since decoded string will be shorter in length, and
566a01eb745d49bd866971062388cd11d525b60dDavid Lawrence * the caller allocated 'buf' so that its length is not
566a01eb745d49bd866971062388cd11d525b60dDavid Lawrence * less than 'fromlen', we don't have to worry about overflow.
566a01eb745d49bd866971062388cd11d525b60dDavid Lawrence while (fromlen-- > 0) {
facb97777a972f6c8035ca3e762a6a9248c12897Bob Halley x = c - 'a';
facb97777a972f6c8035ca3e762a6a9248c12897Bob Halley x = c - 'A';
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence /* Check if the padding bits are all zero. */
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence if (bitlen > 0 && (bitbuf & ((1 << bitlen) - 1)) != 0) {
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence WARNING(("mdn__lace_convert: non-zero padding\n"));
694c897b20f06f8a5349fd9ac5df93947f6f5a2aBob Halley * Now 'buf' holds the decoded bytes. Rebuild the
694c897b20f06f8a5349fd9ac5df93947f6f5a2aBob Halley * original UTF-16 string.
1443aa0adf4d262abdf2721a5239acd4812cdc06Bob Halley * Not compressed.
083699db84de2f7cc534c06ed3502248329145d4Bob Halley /* number of bytes must be even. */
1ce985ab3c6670662d555c108b35fed84a6a1001David Lawrence for (p = buf + 1, q = buf; len > 0; p += 2, q++, len -= 2) {
a2171e092382f8f8a72b1f73436ddf93918c7719Bob Halley * This string must have been compressed.
694c897b20f06f8a5349fd9ac5df93947f6f5a2aBob Halley WARNING(("mdn__lace_convert: decoded string is not "
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley "compressed, though it should be.\n"));
7c0876aa42e6abaa8779bcb83962ccf20a9f4da3Bob Halley * Compressed.
7c0876aa42e6abaa8779bcb83962ccf20a9f4da3Bob Halley unsigned short high = 0; /* initialize for lint */
491b48ec3f3ef014312688776ddbd4eab8a2c10cMichael Graff /* Get COUNT and HIGH. */
1922518d7f7b5e3e77b8e1c92569c98268b9c192Andreas Gustafsson * This string must not have been compressed.
9cda9dc86efa0dde8f906759c4e3279da028b5f4Bob Halley "compressed, though it shouldn't.\n"));
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrencelace_encode(const char *from, size_t fromlen, char *to, size_t tolen) {
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence unsigned short *buf;
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence unsigned short local_buf[LACE_BUF_SIZE]; /* UTF-16 */
4c5faa6bcf41d8ba253b872a04105a2fcc88c07bMichael Graff * Convert to UTF-16.
6c327669ba1d9eca870572b930c46f43e781d4a3Andreas Gustafsson buf = realloc(buf, sizeof(*buf) * buflen);
8671e8306b3f18abf0e19c2fb9d49205962e7ab7David Lawrence } else if (r == mdn_success) {
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * Compress, encode in base-32 and output.
40f24178432de09181bc603cc90110546a0ddca2Mark Andrewslace_encode_utf16(const unsigned short *p, size_t len,
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews unsigned long bitbuf = 0; /* bit stream buffer */
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews /* prepend non-compression mark */
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews for (i = 0; i <= len; i++) {
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews * End of data. Flush. The current draft (-00)
40f24178432de09181bc603cc90110546a0ddca2Mark Andrews * doesn't seem to define which value to use for
afb4ad8f988591bccae0ee2ac73b2fef5d969366Mark Andrews * padding (which it should). We assume zero.
afb4ad8f988591bccae0ee2ac73b2fef5d969366Mark Andrews bitbuf <<= 5 - (bitlen % 5); /* padding with zero */
afb4ad8f988591bccae0ee2ac73b2fef5d969366Mark Andrews } else if (compress) {
afb4ad8f988591bccae0ee2ac73b2fef5d969366Mark Andrews * Get the number of consecutive characters
afb4ad8f988591bccae0ee2ac73b2fef5d969366Mark Andrews * with the same high byte.
a272a556314a892c0bd73bc302e08249f3d99ec2Mark Andrews * Output bits in 'bitbuf' in 5-bit unit.
700f1442882eda0cce05a51e8c6f820c51054e8eMark Andrews /* Get top 5 bits. */
6182613ef54ebb8369d951ffa4431c49b75cec51Mark Andrews /* Encode. */
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrenceis_compress_effective(unsigned short *p, size_t len) {
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence unsigned short last_high = 0x1; /* initialize with an invalid value */
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson * Find the number of HIGH value in the compressed string.
ca485ab26fffa241a3eac1899b2d2012dd1fdb73Andreas Gustafsson for (i = 0; i < len; i++) {
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * Compressed string would take 2 * 'nhigh' + 'len' bytes,
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * while the original (uncomressed) string would take 2 * 'len'.
df3c4c7988b9bae7d121a8ac9ed17a23366a948dDavid Lawrence * So the difference is 2 * 'nhigh' - len.
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley return (0); /* Nope. */