ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina/*
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina SSSD
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina Authors:
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina Stephen Gallagher <sgallagh@redhat.com>
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina Copyright (C) 2011 Red Hat
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina This program is free software; you can redistribute it and/or modify
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina it under the terms of the GNU General Public License as published by
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina the Free Software Foundation; either version 3 of the License, or
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina (at your option) any later version.
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina This program is distributed in the hope that it will be useful,
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina but WITHOUT ANY WARRANTY; without even the implied warranty of
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina GNU General Public License for more details.
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina You should have received a copy of the GNU General Public License
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina along with this program. If not, see <http://www.gnu.org/licenses/>.
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina*/
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina#include "config.h"
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina#include <string.h>
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina#include <errno.h>
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina#ifdef HAVE_LIBUNISTRING
365fe7479c753f198430812337a7ba8cdb0baf7dLukas Slebodnik#include <stdlib.h>
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina#include <unistr.h>
365fe7479c753f198430812337a7ba8cdb0baf7dLukas Slebodnik#include <unicase.h>
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina#elif defined(HAVE_GLIB2)
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina#include <glib.h>
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina#endif
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina#include "sss_utf8.h"
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina#ifdef HAVE_LIBUNISTRING
365fe7479c753f198430812337a7ba8cdb0baf7dLukas Slebodnikvoid sss_utf8_free(void *ptr)
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina{
365fe7479c753f198430812337a7ba8cdb0baf7dLukas Slebodnik return free(ptr);
365fe7479c753f198430812337a7ba8cdb0baf7dLukas Slebodnik}
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina#elif defined(HAVE_GLIB2)
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březinavoid sss_utf8_free(void *ptr)
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina{
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina return g_free(ptr);
365fe7479c753f198430812337a7ba8cdb0baf7dLukas Slebodnik}
365fe7479c753f198430812337a7ba8cdb0baf7dLukas Slebodnik#else
365fe7479c753f198430812337a7ba8cdb0baf7dLukas Slebodnik#error No unicode library
365fe7479c753f198430812337a7ba8cdb0baf7dLukas Slebodnik#endif
365fe7479c753f198430812337a7ba8cdb0baf7dLukas Slebodnik
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina#ifdef HAVE_LIBUNISTRING
365fe7479c753f198430812337a7ba8cdb0baf7dLukas Slebodnikuint8_t *sss_utf8_tolower(const uint8_t *s, size_t len, size_t *_nlen)
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina{
365fe7479c753f198430812337a7ba8cdb0baf7dLukas Slebodnik size_t llen;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina uint8_t *lower;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina lower = u8_tolower(s, len, NULL, NULL, NULL, &llen);
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina if (!lower) return NULL;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina if (_nlen) *_nlen = llen;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina return lower;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina}
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina#elif defined(HAVE_GLIB2)
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březinauint8_t *sss_utf8_tolower(const uint8_t *s, size_t len, size_t *_nlen)
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina{
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina gchar *glower;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina size_t nlen;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina uint8_t *lower;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina glower = g_utf8_strdown((const gchar *) s, len);
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina if (!glower) return NULL;
365fe7479c753f198430812337a7ba8cdb0baf7dLukas Slebodnik
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina /* strlen() is safe here because g_utf8_strdown() always null-terminates */
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina nlen = strlen(glower);
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina lower = g_malloc(nlen);
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina if (!lower) {
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina g_free(glower);
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina return NULL;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina }
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina memcpy(lower, glower, nlen);
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina g_free(glower);
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina if (_nlen) *_nlen = nlen;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina return (uint8_t *) lower;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina}
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina#else
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina#error No unicode library
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina#endif
365fe7479c753f198430812337a7ba8cdb0baf7dLukas Slebodnik
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina#ifdef HAVE_LIBUNISTRING
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březinabool sss_utf8_check(const uint8_t *s, size_t n)
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina{
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina if (u8_check(s, n) == NULL) {
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina return true;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina }
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina return false;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina}
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina#elif defined(HAVE_GLIB2)
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březinabool sss_utf8_check(const uint8_t *s, size_t n)
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina{
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina return g_utf8_validate((const gchar *)s, n, NULL);
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina}
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina#else
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina#error No unicode library
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina#endif
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina/* Returns EOK on match, ENOTUNIQ if comparison succeeds but
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina * does not match.
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina * May return other errno error codes on failure
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina */
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina#ifdef HAVE_LIBUNISTRING
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březinaerrno_t sss_utf8_case_eq(const uint8_t *s1, const uint8_t *s2)
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina{
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina /* Do a case-insensitive comparison.
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina * The input must be encoded in UTF8.
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina * We have no way of knowing the language,
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina * so we'll pass NULL for the language and
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina * hope for the best.
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina */
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina int ret;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina int resultp;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina size_t n1, n2;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina errno = 0;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina n1 = u8_strlen(s1);
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina n2 = u8_strlen(s2);
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina ret = u8_casecmp(s1, n1,
365fe7479c753f198430812337a7ba8cdb0baf7dLukas Slebodnik s2, n2,
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina NULL, NULL,
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina &resultp);
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina if (ret < 0) {
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina /* An error occurred */
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina return errno;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina }
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
365fe7479c753f198430812337a7ba8cdb0baf7dLukas Slebodnik if (resultp == 0) {
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina return EOK;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina }
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina return ENOMATCH;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina}
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina#elif defined(HAVE_GLIB2)
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březinaerrno_t sss_utf8_case_eq(const uint8_t *s1, const uint8_t *s2)
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina{
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina gchar *gs1;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina gchar *gs2;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina gssize n1, n2;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina gint gret;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina errno_t ret;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina n1 = g_utf8_strlen((const gchar *)s1, -1);
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina n2 = g_utf8_strlen((const gchar *)s2, -1);
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina gs1 = g_utf8_casefold((const gchar *)s1, n1);
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina if (gs1 == NULL) {
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina return ENOMEM;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina }
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina gs2 = g_utf8_casefold((const gchar *)s2, n2);
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina if (gs2 == NULL) {
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina return ENOMEM;
365fe7479c753f198430812337a7ba8cdb0baf7dLukas Slebodnik }
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina gret = g_utf8_collate(gs1, gs2);
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina if (gret == 0) {
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina ret = EOK;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina } else {
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina ret = ENOMATCH;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina }
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina g_free(gs1);
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina g_free(gs2);
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina return ret;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina}
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina#else
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina#error No unicode library
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina#endif
365fe7479c753f198430812337a7ba8cdb0baf7dLukas Slebodnik
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březinabool sss_string_equal(bool cs, const char *s1, const char *s2)
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina{
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina if (cs) {
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina return strcmp(s1, s2) == 0;
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina }
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina return sss_utf8_case_eq((const uint8_t *)s1, (const uint8_t *)s2) == EOK;
365fe7479c753f198430812337a7ba8cdb0baf7dLukas Slebodnik}
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina