5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2004 - 2005 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
20 #include "silcincludes.h"
21 #include "silcstringprep.h"
22 #include <stringprep.h>
24 /* We use GNU Libidn which has stringprep to do the magic. Only bad thing
25 is that its interface is idiotic. We have our own API here in case
26 we'll implement it ourselves later. */
28 /* Prohibited characters as defined by the protocol in Appendix B */
29 const Stringprep_table_element silc_appendix_b[] =
31 {0x000021}, {0x00002A}, {0x00002C}, {0x00003F}, {0x000040},
33 {0x0000AC}, {0x0000AE}, {0x0000AF}, {0x0000B0}, {0x0000B1}, {0x0000B4},
34 {0x0000B6}, {0x0000B8}, {0x0000D7}, {0x0000F7},
35 {0x0002C2, 0x0002C5}, {0x0002D2, 0x0002FF},
36 {0x000374}, {0x000375}, {0x000384}, {0x000385}, {0x0003F6}, {0x000482},
37 {0x00060E}, {0x00060F}, {0x0006E9}, {0x0006FD}, {0x0006FE}, {0x0009F2},
38 {0x0009F3}, {0x0009FA}, {0x000AF1}, {0x000B70},
39 {0x000BF3, 0x000BFA}, {0x000E3F},
40 {0x000F01, 0x000F03}, {0x000F13, 0x000F17}, {0x000F1A, 0x000F1F},
41 {0x000F34}, {0x000F36}, {0x000F38}, {0x000FBE}, {0x000FBF},
42 {0x000FC0, 0x000FC5}, {0x000FC7, 0x000FCF}, {0x0017DB}, {0x001940},
43 {0x0019E0, 0x0019FF}, {0x001FBD}, {0x001FBF, 0x001FC1},
44 {0x001FCD, 0x001FCF}, {0x001FDD, 0x001FDF}, {0x001FED, 0x001FEF},
45 {0x001FFD}, {0x001FFE}, {0x002044}, {0x002052}, {0x00207A, 0x00207C},
46 {0x00208A, 0x00208C}, {0x0020A0, 0x0020B1}, {0x002100, 0x00214F},
47 {0x002150, 0x00218F}, {0x002190, 0x0021FF}, {0x002200, 0x0022FF},
48 {0x002300, 0x0023FF}, {0x002400, 0x00243F}, {0x002440, 0x00245F},
49 {0x002460, 0x0024FF}, {0x002500, 0x00257F}, {0x002580, 0x00259F},
50 {0x0025A0, 0x0025FF}, {0x002600, 0x0026FF}, {0x002700, 0x0027BF},
51 {0x0027C0, 0x0027EF}, {0x0027F0, 0x0027FF}, {0x002800, 0x0028FF},
52 {0x002900, 0x00297F}, {0x002980, 0x0029FF}, {0x002A00, 0x002AFF},
53 {0x002B00, 0x002BFF}, {0x002E9A}, {0x002EF4, 0x002EFF},
54 {0x002FF0, 0x002FFF}, {0x00303B, 0x00303D}, {0x003040},
55 {0x003095, 0x003098}, {0x00309F, 0x0030A0}, {0x0030FF, 0x003104},
56 {0x00312D, 0x003130}, {0x00318F}, {0x0031B8, 0x0031FF},
57 {0x00321D, 0x00321F}, {0x003244, 0x00325F}, {0x00327C, 0x00327E},
58 {0x0032B1, 0x0032BF}, {0x0032CC, 0x0032CF}, {0x0032FF},
59 {0x003377, 0x00337A}, {0x0033DE, 0x0033DF}, {0x0033FF},
61 {0x009FA6, 0x009FFF}, {0x00A48D, 0x00A48F}, {0x00A4A2, 0x00A4A3},
62 {0x00A4B4}, {0x00A4C1}, {0x00A4C5}, {0x00A4C7, 0x00ABFF},
63 {0x00D7A4, 0x00D7FF}, {0x00FA2E, 0x00FAFF}, {0x00FFE0, 0x00FFEE},
64 {0x00FFFC}, {0x010000, 0x01007F}, {0x010080, 0x0100FF},
65 {0x010100, 0x01013F}, {0x01D000, 0x01D0FF}, {0x01D100, 0x01D1FF},
66 {0x01D300, 0x01D35F}, {0x01D400, 0x01D7FF},
71 /* Default SILC Identifier String profile defined by the protocol */
72 const Stringprep_profile stringprep_silc_identifier_prep[] =
74 {STRINGPREP_MAP_TABLE, 0, stringprep_rfc3454_B_1},
75 {STRINGPREP_MAP_TABLE, 0, stringprep_rfc3454_B_2},
76 {STRINGPREP_NFKC, 0, 0},
77 {STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_1_1},
78 {STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_1_2},
79 {STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_2_1},
80 {STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_2_2},
81 {STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_3},
82 {STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_4},
83 {STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_5},
84 {STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_6},
85 {STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_7},
86 {STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_8},
87 {STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_9},
88 {STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_9},
89 {STRINGPREP_PROHIBIT_TABLE, 0, silc_appendix_b},
90 {STRINGPREP_UNASSIGNED_TABLE, ~STRINGPREP_NO_UNASSIGNED,
91 stringprep_rfc3454_A_1},
95 /* Prepares string according to the profile */
98 silc_stringprep(const unsigned char *bin, SilcUInt32 bin_len,
99 SilcStringEncoding bin_encoding,
100 const char *profile_name,
101 SilcStringprepFlags flags,
102 unsigned char **out, SilcUInt32 *out_len,
103 SilcStringEncoding out_encoding)
105 Stringprep_profile_flags f = 0;
106 const Stringprep_profile *profile;
107 unsigned char *utf8s;
108 SilcUInt32 utf8s_len;
111 if (!bin || !bin_len || !profile_name)
112 return SILC_STRINGPREP_ERR;
114 /* Convert string to UTF-8 */
115 utf8s_len = silc_utf8_encoded_len(bin, bin_len, bin_encoding);
117 return SILC_STRINGPREP_ERR_ENCODING;
118 utf8s = silc_calloc(utf8s_len + 1, sizeof(*utf8s));
120 return SILC_STRINGPREP_ERR_OUT_OF_MEMORY;
121 silc_utf8_encode(bin, bin_len, bin_encoding, utf8s, utf8s_len);
124 if (!strcmp(profile_name, SILC_IDENTIFIER_PREP))
125 profile = stringprep_silc_identifier_prep;
127 return SILC_STRINGPREP_ERR_UNSUP_PROFILE;
129 /* Translate flags */
130 if (!(flags & SILC_STRINGPREP_ALLOW_UNASSIGNED))
131 f |= STRINGPREP_NO_UNASSIGNED;
134 ret = stringprep((char *)utf8s, utf8s_len, f, profile);
137 ret = SILC_STRINGPREP_OK;
140 case STRINGPREP_CONTAINS_UNASSIGNED:
141 ret = SILC_STRINGPREP_ERR_UNASSIGNED;
144 case STRINGPREP_CONTAINS_PROHIBITED:
145 ret = SILC_STRINGPREP_ERR_PROHIBITED;
148 case STRINGPREP_BIDI_BOTH_L_AND_RAL:
149 ret = SILC_STRINGPREP_ERR_BIDI_RAL_WITH_L;
152 case STRINGPREP_BIDI_LEADTRAIL_NOT_RAL:
153 ret = SILC_STRINGPREP_ERR_BIDI_RAL;
156 case STRINGPREP_BIDI_CONTAINS_PROHIBITED:
157 ret = SILC_STRINGPREP_ERR_BIDI_PROHIBITED;
160 case STRINGPREP_UNKNOWN_PROFILE:
161 ret = SILC_STRINGPREP_ERR_UNSUP_PROFILE;
164 case STRINGPREP_MALLOC_ERROR:
165 ret = SILC_STRINGPREP_ERR_OUT_OF_MEMORY;
169 ret = SILC_STRINGPREP_ERR;
173 /* Convert to desired output character encoding */
174 if (ret == SILC_STRINGPREP_OK) {
175 if (out && out_len) {
176 if (out_encoding != SILC_STRING_UTF8) {
177 *out_len = silc_utf8_decoded_len(utf8s, strlen(utf8s), out_encoding);
179 *out = silc_calloc(*out_len + 1, sizeof(**out));
181 silc_utf8_decode(utf8s, strlen(utf8s), out_encoding, *out,
184 ret = SILC_STRINGPREP_ERR_OUT_OF_MEMORY;
187 ret = SILC_STRINGPREP_ERR_ENCODING;
190 *out_len = strlen(utf8s);
191 *out = silc_memdup(utf8s, *out_len);
198 return (SilcStringprepStatus)ret;