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