diff options
Diffstat (limited to 'libidn/idn-stub.c')
-rw-r--r-- | libidn/idn-stub.c | 104 |
1 files changed, 74 insertions, 30 deletions
diff --git a/libidn/idn-stub.c b/libidn/idn-stub.c index 1e5cc1f6f9..7f5d22e5aa 100644 --- a/libidn/idn-stub.c +++ b/libidn/idn-stub.c @@ -33,6 +33,77 @@ static void *h; +static int (*to_ascii_lz) (const char *input, char **output, int flags); +static int (*to_unicode_lzlz) (const char *input, char **output, int flags); + + +static void +load_dso (void) +{ + /* Lock protecting the DSO loading. */ + __libc_lock_define_initialized (static, lock); + + __libc_lock_lock (lock); + + /* Retest in case some other thread arrived here at the same time. */ + if (h == NULL) + { + h = __libc_dlopen (LIBCIDN_SO); + + if (h == NULL) + h = (void *) 1l; + else + { + /* Get the function we are interested in. */ + to_ascii_lz = __libc_dlsym (h, "idna_to_ascii_lz"); + to_unicode_lzlz = __libc_dlsym (h, "idna_to_unicode_lzlz"); + if (to_ascii_lz == NULL || to_unicode_lzlz == NULL) + { + __libc_dlclose (h); + h = (void *) 1l; + } + } + } + + __libc_lock_unlock (lock); +} + + +/* Stub to dlopen libcidn.so and invoke the real idna_to_ascii_lz, or + return IDNA_DLOPEN_ERROR on failure. */ +int +__idna_to_unicode_lzlz (const char *input, char **output, int flags) +{ + /* If the input string contains no "xn--" prefix for a component of + the name we can pass it up right away. */ + const char *cp = input; + while (*cp != '\0') + { + if (strncmp (cp, IDNA_ACE_PREFIX, strlen (IDNA_ACE_PREFIX)) == 0) + break; + + /* On to the next part of the name. */ + cp = strchrnul (cp, '.'); + if (*cp == '.') + ++cp; + } + + if (*cp == '\0') + { + *output = (char *) input; + return IDNA_SUCCESS; + } + + if (h == NULL) + load_dso (); + + if (h == (void *) 1l) + return IDNA_DLOPEN_ERROR; + + return to_unicode_lzlz (input, output, flags); +} + + /* Stub to dlopen libcidn.so and invoke the real idna_to_ascii_lz, or return IDNA_DLOPEN_ERROR on failure. */ int @@ -47,39 +118,12 @@ __idna_to_ascii_lz (const char *input, char **output, int flags) if (*cp == '\0') { - *output = strdup (input); - return *output == NULL ? IDNA_MALLOC_ERROR : IDNA_SUCCESS; + *output = (char *) input; + return IDNA_SUCCESS; } - static int (*to_ascii_lz) (const char *input, char **output, int flags); - if (h == NULL) - { - __libc_lock_define_initialized (static, lock); - - __libc_lock_lock (lock); - - /* Retest in case some other thread arrived here at the same time. */ - if (h == NULL) - { - h = __libc_dlopen (LIBCIDN_SO); - - if (h == NULL) - h = (void *) 1l; - else - { - /* Get the function we are interested in. */ - to_ascii_lz = __libc_dlsym (h, "idna_to_ascii_lz"); - if (to_ascii_lz == NULL) - { - __libc_dlclose (h); - h = (void *) 1l; - } - } - } - - __libc_lock_unlock (lock); - } + load_dso (); if (h == (void *) 1l) return IDNA_DLOPEN_ERROR; |