diff options
Diffstat (limited to 'avahi-core/util.c')
| -rw-r--r-- | avahi-core/util.c | 236 | 
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); +    } +}  | 
