dict.c revision 5f5870385cff47efd2f58e7892f251cf13761528
a8c5a86d183db25a57bf193c06b41e092ec2e151Timo Sirainen/* Copyright (c) 2005-2012 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen#include "array.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "str.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "dict-sql.h"
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen#include "dict-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic ARRAY_DEFINE(dict_drivers, struct dict *);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
463e82bdf0e990f4f2252d2b53ea23a5abe5883cTimo Sirainenstatic struct dict *dict_driver_lookup(const char *name)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen struct dict *const *dicts;
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen array_foreach(&dict_drivers, dicts) {
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen struct dict *dict = *dicts;
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen if (strcmp(dict->name, name) == 0)
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen return dict;
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen }
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen return NULL;
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen}
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainenvoid dict_driver_register(struct dict *driver)
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen{
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (!array_is_created(&dict_drivers))
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen i_array_init(&dict_drivers, 8);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (dict_driver_lookup(driver->name) != NULL) {
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen i_fatal("dict_driver_register(%s): Already registered",
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen driver->name);
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen }
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen array_append(&dict_drivers, &driver, 1);
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen}
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainenvoid dict_driver_unregister(struct dict *driver)
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen{
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen struct dict *const *dicts;
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen unsigned int idx = -1U;
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen array_foreach(&dict_drivers, dicts) {
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen if (*dicts == driver) {
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen idx = array_foreach_idx(&dict_drivers, dicts);
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen break;
c21c33a8c98972c45349066fc76ac9e2c05013c1Timo Sirainen }
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen }
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen i_assert(idx != -1U);
7bd3f5614e0dd2324dd1015f084de72c0b069a1aTimo Sirainen array_delete(&dict_drivers, idx, 1);
7bd3f5614e0dd2324dd1015f084de72c0b069a1aTimo Sirainen
7bd3f5614e0dd2324dd1015f084de72c0b069a1aTimo Sirainen if (array_count(&dict_drivers) == 0)
7bd3f5614e0dd2324dd1015f084de72c0b069a1aTimo Sirainen array_free(&dict_drivers);
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen}
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainenvoid dict_drivers_register_builtin(void)
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen dict_driver_register(&dict_driver_client);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen dict_driver_register(&dict_driver_file);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen}
e6d7d19c328e7043ad35d5a52c1617bde915a16fTimo Sirainen
d7095f3a4466fbb78b2d5eb3d322bc15a5b0ab1fTimo Sirainenvoid dict_drivers_unregister_builtin(void)
153de7823e64c67678b3fc95719c41a8ec5b864dTimo Sirainen{
153de7823e64c67678b3fc95719c41a8ec5b864dTimo Sirainen dict_driver_unregister(&dict_driver_client);
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen dict_driver_unregister(&dict_driver_file);
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainen}
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
e6d7d19c328e7043ad35d5a52c1617bde915a16fTimo Sirainenstruct dict *dict_init(const char *uri, enum dict_data_type value_type,
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen const char *username, const char *base_dir)
9315dd69233d554452df0c12bc57002d2042a8f4Timo Sirainen{
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen struct dict *dict;
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen const char *p, *name;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
538c58fc95200fcc5e91abdda8b912b574a2f968Timo Sirainen i_assert(username != NULL);
b99f3f908d51f4d1f7628bdf2cc6100cd8587656Timo Sirainen
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen p = strchr(uri, ':');
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (p == NULL) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen i_error("Dictionary URI is missing ':': %s", uri);
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen return NULL;
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen T_BEGIN {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen name = t_strdup_until(uri, p);
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen dict = dict_driver_lookup(name);
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen if (dict == NULL)
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen i_error("Unknown dict module: %s", name);
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen } T_END;
b99f3f908d51f4d1f7628bdf2cc6100cd8587656Timo Sirainen
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen return dict == NULL ? NULL :
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen dict->v.init(dict, p+1, value_type, username, base_dir);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenvoid dict_deinit(struct dict **_dict)
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen{
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen struct dict *dict = *_dict;
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen *_dict = NULL;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen dict->v.deinit(dict);
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen}
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainenint dict_wait(struct dict *dict)
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen{
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen return dict->v.wait == NULL ? 1 : dict->v.wait(dict);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic bool dict_key_prefix_is_valid(const char *key)
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen{
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen return strncmp(key, DICT_PATH_SHARED, strlen(DICT_PATH_SHARED)) == 0 ||
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen strncmp(key, DICT_PATH_PRIVATE, strlen(DICT_PATH_PRIVATE)) == 0;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen}
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint dict_lookup(struct dict *dict, pool_t pool, const char *key,
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen const char **value_r)
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen{
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen i_assert(dict_key_prefix_is_valid(key));
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen return dict->v.lookup(dict, pool, key, value_r);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen}
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainenstruct dict_iterate_context *
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainendict_iterate_init(struct dict *dict, const char *path,
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen enum dict_iterate_flags flags)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *paths[2];
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen paths[0] = path;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen paths[1] = NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return dict_iterate_init_multiple(dict, paths, flags);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen}
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainenstruct dict_iterate_context *
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainendict_iterate_init_multiple(struct dict *dict, const char *const *paths,
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen enum dict_iterate_flags flags)
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen{
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen unsigned int i;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen i_assert(paths[0] != NULL);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen for (i = 0; paths[i] != NULL; i++)
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen i_assert(dict_key_prefix_is_valid(paths[i]));
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen return dict->v.iterate_init(dict, paths, flags);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen}
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenbool dict_iterate(struct dict_iterate_context *ctx,
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen const char **key_r, const char **value_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ctx->dict->v.iterate(ctx, key_r, value_r);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen}
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainenint dict_iterate_deinit(struct dict_iterate_context **_ctx)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen{
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen struct dict_iterate_context *ctx = *_ctx;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen *_ctx = NULL;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen return ctx->dict->v.iterate_deinit(ctx);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen}
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainenstruct dict_transaction_context *dict_transaction_begin(struct dict *dict)
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen{
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen return dict->v.transaction_init(dict);
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen}
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainenint dict_transaction_commit(struct dict_transaction_context **_ctx)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen{
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen struct dict_transaction_context *ctx = *_ctx;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen *_ctx = NULL;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen return ctx->dict->v.transaction_commit(ctx, FALSE, NULL, NULL);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainenvoid dict_transaction_commit_async(struct dict_transaction_context **_ctx,
b9ec0443d7d8afebfe61c17a9d692d6fad30c276Timo Sirainen dict_transaction_commit_callback_t *callback,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen void *context)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct dict_transaction_context *ctx = *_ctx;
b9ec0443d7d8afebfe61c17a9d692d6fad30c276Timo Sirainen
23079bf0a6e7489c5f542b0b897a71bdfd884a51Timo Sirainen *_ctx = NULL;
23079bf0a6e7489c5f542b0b897a71bdfd884a51Timo Sirainen ctx->dict->v.transaction_commit(ctx, TRUE, callback, context);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen}
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainenvoid dict_transaction_rollback(struct dict_transaction_context **_ctx)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen{
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen struct dict_transaction_context *ctx = *_ctx;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen *_ctx = NULL;
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen ctx->dict->v.transaction_rollback(ctx);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen}
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainenvoid dict_set(struct dict_transaction_context *ctx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *key, const char *value)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen{
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen i_assert(dict_key_prefix_is_valid(key));
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen ctx->dict->v.set(ctx, key, value);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen ctx->changed = TRUE;
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen}
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainenvoid dict_unset(struct dict_transaction_context *ctx,
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen const char *key)
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen{
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen i_assert(dict_key_prefix_is_valid(key));
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->dict->v.unset(ctx, key);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->changed = TRUE;
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenvoid dict_atomic_inc(struct dict_transaction_context *ctx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *key, long long diff)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(dict_key_prefix_is_valid(key));
68b3667c9ee95951d7c3e03b19b2d37abbaa5736Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (diff != 0) {
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen ctx->dict->v.atomic_inc(ctx, key, diff);
68b3667c9ee95951d7c3e03b19b2d37abbaa5736Timo Sirainen ctx->changed = TRUE;
1df526903ed039e8ff966a223c43b8d04eddf3c7Phil Carmody }
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen}
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainenconst char *dict_escape_string(const char *str)
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen{
68b3667c9ee95951d7c3e03b19b2d37abbaa5736Timo Sirainen const char *p;
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen string_t *ret;
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen /* see if we need to escape it */
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen for (p = str; *p != '\0'; p++) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (*p == '/' || *p == '\\')
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen break;
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody }
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody if (*p == '\0')
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody return str;
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody /* escape */
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody ret = t_str_new((size_t) (p - str) + 128);
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody str_append_n(ret, str, (size_t) (p - str));
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody for (; *p != '\0'; p++) {
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody switch (*p) {
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody case '/':
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody str_append_c(ret, '\\');
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody str_append_c(ret, '|');
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody break;
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainen case '\\':
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainen str_append_c(ret, '\\');
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainen str_append_c(ret, '\\');
070df93a3014ad4b2eb8754af65128c9f9a72e4ePhil Carmody break;
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainen default:
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainen str_append_c(ret, *p);
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody break;
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainen }
070df93a3014ad4b2eb8754af65128c9f9a72e4ePhil Carmody }
070df93a3014ad4b2eb8754af65128c9f9a72e4ePhil Carmody return str_c(ret);
74896b89e1d82819d710f9322cf7c9e72d5841adPhil Carmody}
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainen
74896b89e1d82819d710f9322cf7c9e72d5841adPhil Carmodyconst char *dict_unescape_string(const char *str)
74896b89e1d82819d710f9322cf7c9e72d5841adPhil Carmody{
74896b89e1d82819d710f9322cf7c9e72d5841adPhil Carmody const char *p;
74896b89e1d82819d710f9322cf7c9e72d5841adPhil Carmody string_t *ret;
74896b89e1d82819d710f9322cf7c9e72d5841adPhil Carmody
74896b89e1d82819d710f9322cf7c9e72d5841adPhil Carmody /* see if we need to unescape it */
74896b89e1d82819d710f9322cf7c9e72d5841adPhil Carmody for (p = str; *p != '\0'; p++) {
74896b89e1d82819d710f9322cf7c9e72d5841adPhil Carmody if (*p == '\\')
4e6629cb5d5e7f67d5023eda540105d32df5f2baPhil Carmody break;
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody }
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody
aba9cc9bf97576c0ca653d4e218567e617061029Phil Carmody if (*p == '\0')
aba9cc9bf97576c0ca653d4e218567e617061029Phil Carmody return str;
aba9cc9bf97576c0ca653d4e218567e617061029Phil Carmody
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody /* unescape */
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody ret = t_str_new((size_t) (p - str) + strlen(p) + 1);
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody str_append_n(ret, str, (size_t) (p - str));
4e6629cb5d5e7f67d5023eda540105d32df5f2baPhil Carmody
4e6629cb5d5e7f67d5023eda540105d32df5f2baPhil Carmody for (; *p != '\0'; p++) {
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody if (*p != '\\')
1df526903ed039e8ff966a223c43b8d04eddf3c7Phil Carmody str_append_c(ret, *p);
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody else {
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody if (*++p == '|')
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody str_append_c(ret, '/');
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody else if (*p == '\0')
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody break;
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody else
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody str_append_c(ret, *p);
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody }
1df526903ed039e8ff966a223c43b8d04eddf3c7Phil Carmody }
1df526903ed039e8ff966a223c43b8d04eddf3c7Phil Carmody return str_c(ret);
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody}
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody