{0}
};
+/* Identifier string case folding and normalizing */
+const Stringprep_profile stringprep_silc_identifierc_prep[] =
+{
+ {STRINGPREP_MAP_TABLE, 0, stringprep_rfc3454_B_1},
+ {STRINGPREP_MAP_TABLE, 0, stringprep_rfc3454_B_2},
+ {STRINGPREP_NFKC, 0, 0},
+ {0}
+};
+
+/* Case folding and normalizing */
+const Stringprep_profile stringprep_silc_casefold_prep[] =
+{
+ {STRINGPREP_MAP_TABLE, 0, stringprep_rfc3454_B_2},
+ {STRINGPREP_NFKC, 0, 0},
+ {0}
+};
+
+
/* Prepares string according to the profile */
SilcStringprepStatus
/* Check profile. */
if (!strcmp(profile_name, SILC_IDENTIFIER_PREP))
profile = stringprep_silc_identifier_prep;
+ else if (!strcmp(profile_name, SILC_IDENTIFIERC_PREP))
+ profile = stringprep_silc_identifierc_prep;
+ else if (!strcmp(profile_name, SILC_CASEFOLD_PREP))
+ profile = stringprep_silc_casefold_prep;
else
return SILC_STRINGPREP_ERR_UNSUP_PROFILE;
/* Profiles */
#define SILC_IDENTIFIER_PREP "silc-identifier-prep"
+#define SILC_IDENTIFIERC_PREP "silc-identifierc-prep"
+#define SILC_CASEFOLD_PREP "silc-casefold-prep"
/****f* silcutil/SilcStringprep/silc_stringprep
*
*
* Available profile names:
*
- * SILC_IDENTIFIER_PREP
+ * SILC_IDENTIFIER_PREP Prepares SILC identifier strings
+ * SILC_IDENTIFIERC_PREP Casefolds identifier strings
+ * SILC_CASEFOLD_PREP Casefolding and normalizing
*
***/
SilcStringprepStatus
return utf8s;
}
+
+/* Same as above but does not allocate memory, just checks the
+ validity of the string. */
+
+bool silc_identifier_verify(const unsigned char *identifier,
+ SilcUInt32 identifier_len,
+ SilcStringEncoding identifier_encoding,
+ SilcUInt32 max_allowed_length)
+{
+ SilcStringprepStatus status;
+
+ if (!identifier || !identifier_len)
+ return FALSE;
+
+ if (max_allowed_length && identifier_len > max_allowed_length)
+ return FALSE;
+
+ status = silc_stringprep(identifier, identifier_len,
+ identifier_encoding, SILC_IDENTIFIER_PREP, 0,
+ NULL, NULL, SILC_STRING_UTF8);
+ if (status != SILC_STRINGPREP_OK) {
+ SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));
+ return FALSE;
+ }
+
+ return TRUE;
+}
SilcUInt32 max_allowed_length,
SilcUInt32 *out_len);
+/****f* silcutil/SilcStrUtilAPI/silc_identifier_verify
+ *
+ * SYNOPSIS
+ *
+ * bool
+ * silc_identifier_check(const unsigned char *identifier,
+ * SilcUInt32 identifier_len,
+ * SilcStringEncoding identifier_encoding,
+ * SilcUInt32 max_allowed_length);
+ *
+ * DESCRIPTION
+ *
+ * Checks that the 'identifier' string is valid identifier string
+ * and does not contain any unassigned or prohibited character. This
+ * function is used to check for valid nicknames, channel names,
+ * server names, usernames, hostnames, service names, algorithm names,
+ * other security property names, and SILC Public Key name.
+ *
+ * If the 'max_allowed_length' is non-zero the identifier cannot be
+ * longer than that, and NULL is returned if it is. If zero (0), no
+ * length limit exist. For nicknames the max length must be 128 bytes
+ * and for channel names 256 bytes. Other identifiers has no default
+ * limit, but application may choose one anyway.
+ *
+ * Returns TRUE if the string is valid and FALSE if it is prohibited.
+ *
+ ***/
+bool silc_identifier_verify(const unsigned char *identifier,
+ SilcUInt32 identifier_len,
+ SilcStringEncoding identifier_encoding,
+ SilcUInt32 max_allowed_length);
+
#endif /* SILCSTRUTIL_H */
return h;
}
+/* Hash UTF-8 string */
+
+SilcUInt32 silc_hash_utf8_string(void *key, void *user_context)
+{
+ unsigned char *s = (unsigned char *)key;
+ SilcUInt32 h = 0, g;
+
+ while (*s != '\0') {
+ h = (h << 4) + *s;
+ if ((g = h & 0xf0000000)) {
+ h = h ^ (g >> 24);
+ h = h ^ g;
+ }
+ s++;
+ }
+
+ return h;
+}
+
/* Basic hash function to hash integers. May be used with the SilcHashTable. */
SilcUInt32 silc_hash_uint(void *key, void *user_context)
return !memcmp(key1, key2, len);
}
+/* Compares UTF-8 string. */
+
+bool silc_hash_utf8_compare(void *key1, void *key2, void *user_context)
+{
+ int l1 = strlen((char *)key1);
+ int l2 = strlen((char *)key2);
+ if (l1 > l2)
+ l2 = l1;
+ return !memcmp(key1, key2, l2);
+}
+
/* Compares two SILC Public keys. It may be used as SilcHashTable
comparison function. */
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2003 Pekka Riikonen
+ Copyright (C) 1997 - 2005 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
***/
SilcUInt32 silc_hash_string(void *key, void *user_context);
+/****f* silcutil/SilcUtilAPI/silc_hash_utf8_string
+ *
+ * SYNOPSIS
+ *
+ * SilcUInt32 silc_hash_utf8_string(void *key, void *user_context);
+ *
+ * DESCRIPTION
+ *
+ * Basic has function to hash UTF-8 strings. May be used with the
+ * SilcHashTable. Used with identifier strings. The key is
+ * expected to be casefolded.
+ *
+ ***/
+SilcUInt32 silc_hash_utf8_string(void *key, void *user_context);
+
/****f* silcutil/SilcUtilAPI/silc_hash_uint
*
* SYNOPSIS
***/
bool silc_hash_data_compare(void *key1, void *key2, void *user_context);
+/****f* silcutil/SilcUtilAPI/silc_hash_utf8_compare
+ *
+ * SYNOPSIS
+ *
+ * bool silc_hash_utf8_compare(void *key1, void *key2, void *user_context);
+ *
+ * DESCRIPTION
+ *
+ * Compares UTF-8 strings. Casefolded and NULL terminated strings are
+ * expected. May be used as SilcHashTable comparison function.
+ *
+ ***/
+bool silc_hash_utf8_compare(void *key1, void *key2, void *user_context);
+
/****f* silcutil/SilcUtilAPI/silc_hash_public_key_compare
*
* SYNOPSIS
SILC_STRINGPREP_ERR_PROHIBITED},
};
+const test_st tests_norm[] = {
+ {"Casefold 1",
+ "Pekka Riikonen", "pekka riikonen"},
+ {"Casefold 2",
+ "PEKKA RIIKONEN", "pekka riikonen"},
+ {"Casefold 3",
+ "pekka riikonen", "pekka riikonen"},
+ {"Casefold 4",
+ "#ksPPPAA", "#kspppaa"},
+ {"Normal casefold",
+ "Foobbeli-BofJFlkJDF", "foobbeli-bofjflkjdf"},
+ {"Nothing",
+ "sauna.silcnet.org", "sauna.silcnet.org"},
+ {"Locale test",
+ "Päivää", "päivää", 0, SILC_STRING_LOCALE},
+ {"Locale test2",
+ "#öäöö/&#\\#(&(&#(.äöäÄÖäÄÖÄÖ^'",
+ "#öäöö/&#\\#(&(&#(.äöääöääöäö^'", 0, SILC_STRING_LOCALE},
+};
+
int main(int argc, char **argv)
{
bool success = FALSE;
silc_log_set_debug_string("*stringprep*,*utf8*");
}
+ SILC_LOG_DEBUG(("--- Identifier string tests"));
+
for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
SILC_LOG_DEBUG(("Test case %d", i));
SILC_LOG_DEBUG((" %d: %s", i, tests[i].comment));
out = NULL;
}
+ SILC_LOG_DEBUG(("--- Casefold tests"));
+
+ for (i = 0; i < sizeof(tests_norm) / sizeof(tests_norm[0]); i++) {
+ SILC_LOG_DEBUG(("Test case %d", i));
+ SILC_LOG_DEBUG((" %d: %s", i, tests_norm[i].comment));
+ SILC_LOG_DEBUG((" %d: in: %s", i, tests_norm[i].in));
+ SILC_LOG_DEBUG((" %d: out: %s", i, tests_norm[i].out));
+ SILC_LOG_DEBUG((" %d: ret: %d", i, tests_norm[i].ret));
+
+ if (!tests_norm[i].enc)
+ enc = SILC_STRING_UTF8;
+ else
+ enc = tests_norm[i].enc;
+ ret = silc_stringprep(tests_norm[i].in, strlen(tests_norm[i].in),
+ enc, SILC_CASEFOLD_PREP, 0,
+ &out, &out_len, enc);
+ if (ret != SILC_STRINGPREP_OK) {
+ if (tests_norm[i].ret != SILC_STRINGPREP_OK) {
+ SILC_LOG_DEBUG((" %d: Expected ret %d", i, ret));
+ } else {
+ SILC_LOG_DEBUG(("%d: Error: %d", i, ret));
+ goto err;
+ }
+ } else {
+ SILC_LOG_DEBUG((" %d: prepared out: %s", i, out));
+ SILC_LOG_HEXDUMP((" %d: prepared dump", i), out, out_len);
+ if (memcmp(out, tests_norm[i].out, out_len)) {
+ SILC_LOG_DEBUG((" %d: Output mismatch", i));
+ goto err;
+ }
+ }
+ SILC_LOG_DEBUG((" %d: Output match", i));
+
+ silc_free(out);
+ out = NULL;
+ }
+
success = TRUE;
err: