Back to index

glibc  2.9
idn-stub.c
Go to the documentation of this file.
00001 /* idn-stub.c --- Stub to dlopen libcidn.so and invoke idna_to_ascii_lz.
00002  * Copyright (C) 2003, 2004  Simon Josefsson
00003  *
00004  * This file is part of GNU Libidn.
00005  *
00006  * GNU Libidn is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * GNU Libidn is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with GNU Libidn; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 
00022 #include <ctype.h>
00023 #include <stdio.h>
00024 #include <string.h>
00025 #include <dlfcn.h>
00026 #include <gnu/lib-names.h>
00027 #include <bits/libc-lock.h>
00028 
00029 /* Get specification for idna_to_ascii_lz. */
00030 #include "idna.h"
00031 
00032 /* Handle of the libidn  DSO.  */
00033 static void *h;
00034 
00035 
00036 static int (*to_ascii_lz) (const char *input, char **output, int flags);
00037 static int (*to_unicode_lzlz) (const char *input, char **output, int flags);
00038 
00039 
00040 static void
00041 load_dso (void)
00042 {
00043   /* Lock protecting the DSO loading.  */
00044   __libc_lock_define_initialized (static, lock);
00045 
00046   __libc_lock_lock (lock);
00047 
00048   /* Retest in case some other thread arrived here at the same time.  */
00049   if (h == NULL)
00050     {
00051       h = __libc_dlopen (LIBCIDN_SO);
00052 
00053       if (h == NULL)
00054        h = (void *) 1l;
00055       else
00056        {
00057          /* Get the function we are interested in.  */
00058          to_ascii_lz = __libc_dlsym (h, "idna_to_ascii_lz");
00059          to_unicode_lzlz = __libc_dlsym (h, "idna_to_unicode_lzlz");
00060          if (to_ascii_lz == NULL || to_unicode_lzlz == NULL)
00061            {
00062              __libc_dlclose (h);
00063              h = (void *) 1l;
00064            }
00065        }
00066     }
00067 
00068   __libc_lock_unlock (lock);
00069 }
00070 
00071 
00072 /* Stub to dlopen libcidn.so and invoke the real idna_to_ascii_lz, or
00073    return IDNA_DLOPEN_ERROR on failure.  */
00074 int
00075 __idna_to_unicode_lzlz (const char *input, char **output, int flags)
00076 {
00077   /* If the input string contains no "xn--" prefix for a component of
00078      the name we can pass it up right away.  */
00079   const char *cp = input;
00080   while (*cp != '\0')
00081     {
00082       if (strncmp (cp, IDNA_ACE_PREFIX, strlen (IDNA_ACE_PREFIX)) == 0)
00083        break;
00084 
00085       /* On to the next part of the name.  */
00086       cp = __strchrnul (cp, '.');
00087       if (*cp == '.')
00088        ++cp;
00089     }
00090 
00091   if (*cp == '\0')
00092     {
00093       *output = (char *) input;
00094       return IDNA_SUCCESS;
00095     }
00096 
00097   if (h == NULL)
00098     load_dso ();
00099 
00100   if (h == (void *) 1l)
00101     return IDNA_DLOPEN_ERROR;
00102 
00103   return to_unicode_lzlz (input, output, flags);
00104 }
00105 
00106 
00107 /* Stub to dlopen libcidn.so and invoke the real idna_to_ascii_lz, or
00108    return IDNA_DLOPEN_ERROR on failure.  */
00109 int
00110 __idna_to_ascii_lz (const char *input, char **output, int flags)
00111 {
00112   /* If the input string contains no non-ASCII character the output
00113      string will be the same.  No valid locale encoding does not have
00114      this property.  */
00115   const char *cp = input;
00116   while (*cp != '\0' && isascii (*cp))
00117     ++cp;
00118 
00119   if (*cp == '\0')
00120     {
00121       *output = (char *) input;
00122       return IDNA_SUCCESS;
00123     }
00124 
00125   if (h == NULL)
00126     load_dso ();
00127 
00128   if (h == (void *) 1l)
00129     return IDNA_DLOPEN_ERROR;
00130 
00131   return to_ascii_lz (input, output, flags);
00132 }
00133 
00134 
00135 #ifndef NOT_IN_libc
00136 libc_freeres_fn (unload_libidn)
00137 {
00138   if (h != NULL && h != (void *) 1l)
00139     {
00140       __libc_dlclose (h);
00141       h = (void *) 1l;
00142     }
00143 }
00144 #endif