使用 c api 在 openldap 中插入 utf-8 数据

insert utf-8 data in openldap with c api

在 openldap 数据库中插入 utf-8 数据的正确方法是什么?我在 std::wstring 中有数据,其中 utf-8 编码为:

std::wstring converted = boost::locale::conv::to_utf<wchar_t>(line, "Latin1");

当字符串需要添加一个ldapMod结构时,我使用这个函数:

std::string str8(const std::wstring& s) {
  return boost::locale::conv::utf_to_utf<char>(s);
}

从 wstring 转换为 string。这在我的函数中用于创建 LDAPMod:

LDAPMod ** y::ldap::server::createMods(dataset& values) {
  LDAPMod ** mods = new LDAPMod*[values.elms() + 1];
  mods[values.elms()] = NULL;

  for(int i = 0; i < values.elms(); i++) {
    mods[i] = new LDAPMod;
    data & d = values.get(i);

    switch (d.getType()) {
      case NEW: mods[i]->mod_op = 0; break;
      case ADD: mods[i]->mod_op = LDAP_MOD_ADD; break;
      case MODIFY: mods[i]->mod_op = LDAP_MOD_REPLACE; break;
      case DELETE: mods[i]->mod_op = LDAP_MOD_DELETE; break;
      default: assert(false);
    }

    std::string type = str8(d.getValue(L"type"));
    mods[i]->mod_type = new char[type.size() + 1];
    std::copy(type.begin(), type.end(), mods[i]->mod_type);
    mods[i]->mod_type[type.size()] = '[=13=]';

    mods[i]->mod_vals.modv_strvals = new char*[d.elms(L"values") + 1];
    for(int j = 0; j < d.elms(L"values"); j++) {
      std::string value = str8(d.getValue(L"values", j));
      mods[i]->mod_vals.modv_strvals[j] = new char[value.size() + 1];
      std::copy(value.begin(), value.end(), mods[i]->mod_vals.modv_strvals[j]);
      mods[i]->mod_vals.modv_strvals[j][value.size()] = '[=13=]';
    }

    mods[i]->mod_vals.modv_strvals[d.elms(L"values")] = NULL;
  }

  return mods;
}

生成的 LDAPMod 被传递给 ldap_modify_ext_s 并且只要我只使用 ASCII 字符就可以工作。但是,如果字符串中存在其他字符,我会收到 ldap 操作错误。

我也尝试过使用 ldap 库 (ldap_x_wcs_to_utf8s) 提供的函数,但结果与 boost 转换相同。

错误不在于转换本身,因为如果我将修改转换回 std::wstring 并在我的程序输出中显示它,编码仍然是正确的。

AFAIK openldap 支持 utf-8 很久了,所以我想知道在这个工作之前是否还有其他事情必须完成?

我查看了 openldap client/tools 示例,但该库提供的 utf-8 函数从未在其中使用过。

更新: 我注意到我可以使用 Apache Directory Studio 将 é 之类的 utf-8 字符插入到 ldap 中。我可以在我的 C++ 程序中从 ldap 检索这些值。但是,如果我再次插入相同的字符,而不对该字符串进行任何更改,我将再次遇到 ldap 操作错误。

事实证明,我的代码一点都没有错。我的修改试图将全名存储在 'displayName' 字段和 'gecos' 字段中。但显然 'gecos' 无法处理 utf8 数据。

我们实际上不再使用 gecos。该值仅由于我们几年前使用的某些软件而存在,因此我将其从目录中删除。

很难发现的是,即使日志级别设置为 'parse',这个错误仍然没有出现在日志中。

因为 libldap 是一个难以破解的难题,我将在我正在处理的项目的完整代码中包含一个 link。它可以作为其他程序员的起点。 (我找到的教程中的大部分代码都已过时。)

https://github.com/yvanvds/yATools/tree/master/libadmintools/ldap