summaryrefslogtreecommitdiffstats
path: root/avahi-core/util.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2005-05-13 23:18:13 +0000
committerLennart Poettering <lennart@poettering.net>2005-05-13 23:18:13 +0000
commita3596a5e3ec4937a220e6e60218639e2aba82701 (patch)
treeebe0ef5fe715ba2fd8f604935d50153958b23e28 /avahi-core/util.c
parentefbf5f40328344aff24d55ddb79cd71759a605a4 (diff)
* utf-8 collation of domain names
* case insensitive comparison of domain names git-svn-id: file:///home/lennart/svn/public/avahi/trunk@71 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe
Diffstat (limited to 'avahi-core/util.c')
-rw-r--r--avahi-core/util.c236
1 files changed, 200 insertions, 36 deletions
diff --git a/avahi-core/util.c b/avahi-core/util.c
index fa97eec..086c041 100644
--- a/avahi-core/util.c
+++ b/avahi-core/util.c
@@ -43,19 +43,60 @@ gchar *avahi_get_host_name(void) {
return avahi_normalize_name(t);
}
+static gchar *unescape_uneeded(const gchar *src, gchar *ret_dest, size_t size) {
+ gboolean escaped = FALSE;
+
+ g_assert(src);
+ g_assert(ret_dest);
+ g_assert(size > 0);
+
+ for (; *src; src++) {
+
+ if (!escaped && *src == '\\')
+ escaped = TRUE;
+ else if (escaped && (*src == '.' || *src == '\\')) {
+
+ if ((size -= 2) <= 1) break;
+
+ *(ret_dest++) = '\\';
+ *(ret_dest++) = *src;
+
+ escaped = FALSE;
+ } else {
+ if (--size <= 1) break;
+
+ *(ret_dest++) = *src;
+ escaped = FALSE;
+ }
+
+ }
+
+ *ret_dest = 0;
+
+ return ret_dest;
+}
+
gchar *avahi_normalize_name(const gchar *s) {
- size_t l;
+ gchar tmp[256];
+ gchar *n, *t;
+ guint l;
g_assert(s);
- l = strlen(s);
+ unescape_uneeded(s, tmp, sizeof(tmp));
- if (!l)
+ n = g_utf8_normalize(tmp, -1, G_NORMALIZE_DEFAULT);
+
+ if ((l = strlen(n)) == 0) {
+ g_free(n);
return g_strdup(".");
+ }
- if (s[l-1] == '.')
- return g_strdup(s);
-
- return g_strdup_printf("%s.", s);
+ if (n[l-1] == '.')
+ return n;
+
+ t = g_strdup_printf("%s.", n);
+ g_free(n);
+ return t;
}
gint avahi_timeval_compare(const GTimeVal *a, const GTimeVal *b) {
@@ -158,50 +199,151 @@ gint avahi_age(const GTimeVal *a) {
return avahi_timeval_diff(&now, a);
}
-gboolean avahi_domain_cmp(const gchar *a, const gchar *b) {
- int escaped_a = 0, escaped_b = 0;
- g_assert(a);
- g_assert(b);
+/* Read the first label from string *name, unescape "\" and write it to dest */
+gchar *avahi_unescape_label(const gchar **name, gchar *dest, guint size) {
+ guint i = 0;
+ gchar *d;
+
+ g_assert(dest);
+ g_assert(size > 0);
+ g_assert(name);
- for (;;) {
- /* Check for escape characters "\" */
- if ((escaped_a = *a == '\\'))
- a ++;
+ if (!**name)
+ return NULL;
- if ((escaped_b = *b == '\\'))
- b++;
+ d = dest;
+
+ for (;;) {
+ if (i >= size)
+ return NULL;
- /* Check for string end */
- if (*a == 0 && *b == 0)
- return 0;
+ if (**name == '.') {
+ (*name)++;
+ break;
+ }
- if (*a == 0 && !escaped_b && *b == '.' && *(b+1) == 0)
- return 0;
+ if (**name == 0)
+ break;
+
+ if (**name == '\\') {
+ (*name) ++;
+
+ if (**name == 0)
+ break;
+ }
+
+ *(d++) = *((*name) ++);
+ i++;
+ }
- if (!escaped_a && *a == '.' && *(a+1) == 0 && *b == 0)
- return 0;
+ g_assert(i < size);
+
+ *d = 0;
+
+ return dest;
+}
- /* Compare characters */
- if (escaped_a == escaped_b && *a != *b)
- return *a < *b ? -1 : 1;
+/* Escape "\" and ".", append \0 */
+gchar *avahi_escape_label(const guint8* src, guint src_length, gchar **ret_name, guint *ret_size) {
+ gchar *r;
+
+ g_assert(src);
+ g_assert(ret_name);
+ g_assert(*ret_name);
+ g_assert(ret_size);
+ g_assert(*ret_size > 0);
+
+ r = *ret_name;
+
+ while (src_length > 0) {
+ if (*src == '.' || *src == '\\') {
+ if (*ret_size < 3)
+ return NULL;
+
+ *((*ret_name) ++) = '\\';
+ (*ret_size) --;
+ }
- /* Next characters */
- a++;
- b++;
+ if (*ret_size < 2)
+ return NULL;
+ *((*ret_name)++) = *src;
+ (*ret_size) --;
+
+ src_length --;
+ src++;
}
+
+ **ret_name = 0;
+
+ return r;
+}
+
+static gint utf8_strcasecmp(const gchar *a, const gchar *b) {
+ gchar *ta, *tb;
+ gint r;
+
+ g_assert(a);
+ g_assert(b);
+
+ ta = g_utf8_casefold(a, -1);
+ tb = g_utf8_casefold(b, -1);
+ r = g_utf8_collate(ta, tb);
+ g_free(ta);
+ g_free(tb);
+
+ return r;
}
gboolean avahi_domain_equal(const gchar *a, const gchar *b) {
- return avahi_domain_cmp(a, b) == 0;
+ g_assert(a);
+ g_assert(b);
+
+ if (a == b)
+ return TRUE;
+
+ for (;;) {
+ gchar ca[65], cb[65], *pa, *pb;
+
+ pa = avahi_unescape_label(&a, ca, sizeof(ca));
+ pb = avahi_unescape_label(&b, cb, sizeof(cb));
+
+ if (!pa && !pb)
+ return TRUE;
+ else if ((pa && !pb) || (!pa && pb))
+ return FALSE;
+
+ if (utf8_strcasecmp(pa, pb))
+ return FALSE;
+ }
+
+ return TRUE;
}
-guint avahi_domain_hash(const gchar *p) {
- char t[256];
- strncpy(t, p, sizeof(t)-1);
- t[sizeof(t)-1] = 0;
+gint avahi_binary_domain_cmp(const gchar *a, const gchar *b) {
+ g_assert(a);
+ g_assert(b);
+
+ if (a == b)
+ return 0;
+
+ for (;;) {
+ gchar ca[65], cb[65], *pa, *pb;
+ gint r;
+
+ pa = avahi_unescape_label(&a, ca, sizeof(ca));
+ pb = avahi_unescape_label(&b, cb, sizeof(cb));
- return g_int_hash(t);
+ if (!pa && !pb)
+ return 0;
+ else if (pa && !pb)
+ return 1;
+ else if (!pa && pb)
+ return -1;
+
+ if ((r = strcmp(pa, pb)))
+ return r;
+ }
}
void avahi_hexdump(gconstpointer p, guint size) {
@@ -237,3 +379,25 @@ void avahi_hexdump(gconstpointer p, guint size) {
size -= 16;
}
}
+
+gint avahi_domain_hash(const gchar *s) {
+ guint hash = 0;
+
+ for (;;) {
+ gchar c[65], *n, *m;
+
+ if (!avahi_unescape_label(&s, c, sizeof(c)))
+ return hash;
+
+ if (!c[0])
+ continue;
+
+ n = g_utf8_normalize(c, -1, G_NORMALIZE_DEFAULT);
+ m = g_utf8_strdown(n, -1);
+
+ hash += g_str_hash(m);
+
+ g_free(m);
+ g_free(n);
+ }
+}