chiark / gitweb /
eglibc (2.11.3-4+deb6u3) squeeze-lts; urgency=medium
[eglibc.git] / libidn / idn-stub.c
1 /* idn-stub.c --- Stub to dlopen libcidn.so and invoke idna_to_ascii_lz.
2  * Copyright (C) 2003, 2004  Simon Josefsson
3  *
4  * This file is part of GNU Libidn.
5  *
6  * GNU Libidn is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * GNU Libidn is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with GNU Libidn; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include <ctype.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <dlfcn.h>
26 #include <gnu/lib-names.h>
27 #include <bits/libc-lock.h>
28
29 /* Get specification for idna_to_ascii_lz. */
30 #include "idna.h"
31
32 /* Handle of the libidn  DSO.  */
33 static void *h;
34
35
36 static int (*to_ascii_lz) (const char *input, char **output, int flags);
37 static int (*to_unicode_lzlz) (const char *input, char **output, int flags);
38
39
40 static void
41 load_dso (void)
42 {
43   /* Lock protecting the DSO loading.  */
44   __libc_lock_define_initialized (static, lock);
45
46   __libc_lock_lock (lock);
47
48   /* Retest in case some other thread arrived here at the same time.  */
49   if (h == NULL)
50     {
51       h = __libc_dlopen (LIBCIDN_SO);
52
53       if (h == NULL)
54         h = (void *) 1l;
55       else
56         {
57           /* Get the function we are interested in.  */
58           to_ascii_lz = __libc_dlsym (h, "idna_to_ascii_lz");
59           to_unicode_lzlz = __libc_dlsym (h, "idna_to_unicode_lzlz");
60           if (to_ascii_lz == NULL || to_unicode_lzlz == NULL)
61             {
62               __libc_dlclose (h);
63               h = (void *) 1l;
64             }
65         }
66     }
67
68   __libc_lock_unlock (lock);
69 }
70
71
72 /* Stub to dlopen libcidn.so and invoke the real idna_to_ascii_lz, or
73    return IDNA_DLOPEN_ERROR on failure.  */
74 int
75 __idna_to_unicode_lzlz (const char *input, char **output, int flags)
76 {
77   /* If the input string contains no "xn--" prefix for a component of
78      the name we can pass it up right away.  */
79   const char *cp = input;
80   while (*cp != '\0')
81     {
82       if (strncmp (cp, IDNA_ACE_PREFIX, strlen (IDNA_ACE_PREFIX)) == 0)
83         break;
84
85       /* On to the next part of the name.  */
86       cp = __strchrnul (cp, '.');
87       if (*cp == '.')
88         ++cp;
89     }
90
91   if (*cp == '\0')
92     {
93       *output = (char *) input;
94       return IDNA_SUCCESS;
95     }
96
97   if (h == NULL)
98     load_dso ();
99
100   if (h == (void *) 1l)
101     return IDNA_DLOPEN_ERROR;
102
103   return to_unicode_lzlz (input, output, flags);
104 }
105
106
107 /* Stub to dlopen libcidn.so and invoke the real idna_to_ascii_lz, or
108    return IDNA_DLOPEN_ERROR on failure.  */
109 int
110 __idna_to_ascii_lz (const char *input, char **output, int flags)
111 {
112   /* If the input string contains no non-ASCII character the output
113      string will be the same.  No valid locale encoding does not have
114      this property.  */
115   const char *cp = input;
116   while (*cp != '\0' && isascii (*cp))
117     ++cp;
118
119   if (*cp == '\0')
120     {
121       *output = (char *) input;
122       return IDNA_SUCCESS;
123     }
124
125   if (h == NULL)
126     load_dso ();
127
128   if (h == (void *) 1l)
129     return IDNA_DLOPEN_ERROR;
130
131   return to_ascii_lz (input, output, flags);
132 }
133
134
135 #ifndef NOT_IN_libc
136 libc_freeres_fn (unload_libidn)
137 {
138   if (h != NULL && h != (void *) 1l)
139     {
140       __libc_dlclose (h);
141       h = (void *) 1l;
142     }
143 }
144 #endif