Line data Source code
1 : /*
2 : SSSD
3 :
4 : Authors:
5 : Stephen Gallagher <sgallagh@redhat.com>
6 :
7 : Copyright (C) 2011 Red Hat
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "config.h"
24 :
25 : #include <string.h>
26 : #include <errno.h>
27 :
28 : #ifdef HAVE_LIBUNISTRING
29 : #include <unistr.h>
30 : #include <unicase.h>
31 : #elif defined(HAVE_GLIB2)
32 : #include <glib.h>
33 : #endif
34 :
35 : #include "sss_utf8.h"
36 :
37 : #ifdef HAVE_LIBUNISTRING
38 : void sss_utf8_free(void *ptr)
39 : {
40 : return free(ptr);
41 : }
42 : #elif defined(HAVE_GLIB2)
43 95 : void sss_utf8_free(void *ptr)
44 : {
45 95 : return g_free(ptr);
46 : }
47 : #else
48 : #error No unicode library
49 : #endif
50 :
51 : #ifdef HAVE_LIBUNISTRING
52 : uint8_t *sss_utf8_tolower(const uint8_t *s, size_t len, size_t *_nlen)
53 : {
54 : size_t llen;
55 : uint8_t *lower;
56 :
57 : lower = u8_tolower(s, len, NULL, NULL, NULL, &llen);
58 : if (!lower) return NULL;
59 :
60 : if (_nlen) *_nlen = llen;
61 : return lower;
62 : }
63 : #elif defined(HAVE_GLIB2)
64 95 : uint8_t *sss_utf8_tolower(const uint8_t *s, size_t len, size_t *_nlen)
65 : {
66 : gchar *glower;
67 : size_t nlen;
68 : uint8_t *lower;
69 :
70 95 : glower = g_utf8_strdown((const gchar *) s, len);
71 95 : if (!glower) return NULL;
72 :
73 : /* strlen() is safe here because g_utf8_strdown() always null-terminates */
74 95 : nlen = strlen(glower);
75 :
76 95 : lower = g_malloc(nlen);
77 95 : if (!lower) {
78 0 : g_free(glower);
79 0 : return NULL;
80 : }
81 :
82 95 : memcpy(lower, glower, nlen);
83 95 : g_free(glower);
84 95 : if (_nlen) *_nlen = nlen;
85 95 : return (uint8_t *) lower;
86 : }
87 : #else
88 : #error No unicode library
89 : #endif
90 :
91 : #ifdef HAVE_LIBUNISTRING
92 : bool sss_utf8_check(const uint8_t *s, size_t n)
93 : {
94 : if (u8_check(s, n) == NULL) {
95 : return true;
96 : }
97 : return false;
98 : }
99 :
100 : #elif defined(HAVE_GLIB2)
101 238 : bool sss_utf8_check(const uint8_t *s, size_t n)
102 : {
103 238 : return g_utf8_validate((const gchar *)s, n, NULL);
104 : }
105 :
106 : #else
107 : #error No unicode library
108 : #endif
109 :
110 : /* Returns EOK on match, ENOTUNIQ if comparison succeeds but
111 : * does not match.
112 : * May return other errno error codes on failure
113 : */
114 : #ifdef HAVE_LIBUNISTRING
115 : errno_t sss_utf8_case_eq(const uint8_t *s1, const uint8_t *s2)
116 : {
117 :
118 : /* Do a case-insensitive comparison.
119 : * The input must be encoded in UTF8.
120 : * We have no way of knowing the language,
121 : * so we'll pass NULL for the language and
122 : * hope for the best.
123 : */
124 : int ret;
125 : int resultp;
126 : size_t n1, n2;
127 : errno = 0;
128 :
129 : n1 = u8_strlen(s1);
130 : n2 = u8_strlen(s2);
131 :
132 : ret = u8_casecmp(s1, n1,
133 : s2, n2,
134 : NULL, NULL,
135 : &resultp);
136 : if (ret < 0) {
137 : /* An error occurred */
138 : return errno;
139 : }
140 :
141 : if (resultp == 0) {
142 : return EOK;
143 : }
144 : return ENOMATCH;
145 : }
146 :
147 : #elif defined(HAVE_GLIB2)
148 53 : errno_t sss_utf8_case_eq(const uint8_t *s1, const uint8_t *s2)
149 : {
150 : gchar *gs1;
151 : gchar *gs2;
152 : gssize n1, n2;
153 : gint gret;
154 : errno_t ret;
155 :
156 53 : n1 = g_utf8_strlen((const gchar *)s1, -1);
157 53 : n2 = g_utf8_strlen((const gchar *)s2, -1);
158 :
159 53 : gs1 = g_utf8_casefold((const gchar *)s1, n1);
160 53 : if (gs1 == NULL) {
161 0 : return ENOMEM;
162 : }
163 :
164 53 : gs2 = g_utf8_casefold((const gchar *)s2, n2);
165 53 : if (gs2 == NULL) {
166 0 : return ENOMEM;
167 : }
168 :
169 53 : gret = g_utf8_collate(gs1, gs2);
170 53 : if (gret == 0) {
171 39 : ret = EOK;
172 : } else {
173 14 : ret = ENOMATCH;
174 : }
175 :
176 53 : g_free(gs1);
177 53 : g_free(gs2);
178 :
179 53 : return ret;
180 : }
181 :
182 : #else
183 : #error No unicode library
184 : #endif
185 :
186 40 : bool sss_string_equal(bool cs, const char *s1, const char *s2)
187 : {
188 40 : if (cs) {
189 38 : return strcmp(s1, s2) == 0;
190 : }
191 :
192 2 : return sss_utf8_case_eq((const uint8_t *)s1, (const uint8_t *)s2) == EOK;
193 : }
|