#include <sys_defs.h>
#include <string.h>
#include <msg.h>
#include <stringops.h>
#include <dict.h>
#include <mymalloc.h>
#include <msg.h>
static char *dict_utf8_check_fold(DICT *dict, const char *string,
CONST_CHAR_STAR *err)
{
int fold_flag = (dict->flags & DICT_FLAG_FOLD_ANY);
if (!allascii(string) && valid_utf8_string(string, strlen(string)) == 0) {
if (err)
*err = "malformed UTF-8 or invalid codepoint";
return (0);
}
if (fold_flag != 0 && (fold_flag & (dict->flags & DICT_FLAG_FIXED) ?
DICT_FLAG_FOLD_FIX : DICT_FLAG_FOLD_MUL)) {
if (dict->fold_buf == 0)
dict->fold_buf = vstring_alloc(10);
return (casefold(dict->fold_buf, string));
}
return ((char *) string);
}
static int dict_utf8_check(const char *string, CONST_CHAR_STAR *err)
{
if (!allascii(string) && valid_utf8_string(string, strlen(string)) == 0) {
if (err)
*err = "malformed UTF-8 or invalid codepoint";
return (0);
}
return (1);
}
static const char *dict_utf8_lookup(DICT *dict, const char *key)
{
DICT_UTF8_BACKUP *backup;
const char *utf8_err;
const char *fold_res;
const char *value;
int saved_flags;
if ((fold_res = dict_utf8_check_fold(dict, key, &utf8_err)) == 0) {
msg_warn("%s:%s: non-UTF-8 key \"%s\": %s",
dict->type, dict->name, key, utf8_err);
dict->error = DICT_ERR_NONE;
return (0);
}
saved_flags = (dict->flags & DICT_FLAG_FOLD_ANY);
dict->flags &= ~DICT_FLAG_FOLD_ANY;
backup = dict->utf8_backup;
value = backup->lookup(dict, fold_res);
dict->flags |= saved_flags;
if (value != 0 && dict_utf8_check(value, &utf8_err) == 0) {
msg_warn("%s:%s: key \"%s\": non-UTF-8 value \"%s\": %s",
dict->type, dict->name, key, value, utf8_err);
dict->error = DICT_ERR_CONFIG;
return (0);
} else {
return (value);
}
}
static int dict_utf8_update(DICT *dict, const char *key, const char *value)
{
DICT_UTF8_BACKUP *backup;
const char *utf8_err;
const char *fold_res;
int saved_flags;
int status;
if ((fold_res = dict_utf8_check_fold(dict, key, &utf8_err)) == 0) {
msg_warn("%s:%s: non-UTF-8 key \"%s\": %s",
dict->type, dict->name, key, utf8_err);
dict->error = DICT_ERR_NONE;
return (DICT_STAT_SUCCESS);
}
else if (dict_utf8_check(value, &utf8_err) == 0) {
msg_warn("%s:%s: key \"%s\": non-UTF-8 value \"%s\": %s",
dict->type, dict->name, key, value, utf8_err);
dict->error = DICT_ERR_NONE;
return (DICT_STAT_SUCCESS);
}
else {
saved_flags = (dict->flags & DICT_FLAG_FOLD_ANY);
dict->flags &= ~DICT_FLAG_FOLD_ANY;
backup = dict->utf8_backup;
status = backup->update(dict, fold_res, value);
dict->flags |= saved_flags;
return (status);
}
}
static int dict_utf8_delete(DICT *dict, const char *key)
{
DICT_UTF8_BACKUP *backup;
const char *utf8_err;
const char *fold_res;
int saved_flags;
int status;
if ((fold_res = dict_utf8_check_fold(dict, key, &utf8_err)) == 0) {
msg_warn("%s:%s: non-UTF-8 key \"%s\": %s",
dict->type, dict->name, key, utf8_err);
dict->error = DICT_ERR_NONE;
return (DICT_STAT_SUCCESS);
}
else {
saved_flags = (dict->flags & DICT_FLAG_FOLD_ANY);
dict->flags &= ~DICT_FLAG_FOLD_ANY;
backup = dict->utf8_backup;
status = backup->delete(dict, fold_res);
dict->flags |= saved_flags;
return (status);
}
}
DICT *dict_utf8_activate(DICT *dict)
{
const char myname[] = "dict_utf8_activate";
DICT_UTF8_BACKUP *backup;
if (util_utf8_enable == 0)
msg_panic("%s: Unicode support is not available", myname);
if ((dict->flags & DICT_FLAG_UTF8_REQUEST) == 0)
msg_panic("%s: %s:%s does not request Unicode support",
myname, dict->type, dict->name);
if ((dict->flags & DICT_FLAG_UTF8_ACTIVE) || dict->utf8_backup != 0)
msg_panic("%s: %s:%s Unicode support is already activated",
myname, dict->type, dict->name);
backup = dict->utf8_backup = (DICT_UTF8_BACKUP *) mymalloc(sizeof(*backup));
backup->lookup = dict->lookup;
backup->update = dict->update;
backup->delete = dict->delete;
dict->lookup = dict_utf8_lookup;
dict->update = dict_utf8_update;
dict->delete = dict_utf8_delete;
dict->flags |= DICT_FLAG_UTF8_ACTIVE;
return (dict);
}