dict.c revision 31257b47d47510ceb093a6b218810a1a5b830c55
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2005-2012 Dovecot authors, see the included COPYING file */
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen#include "lib.h"
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen#include "array.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "str.h"
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen#include "dict-sql.h"
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen#include "dict-private.h"
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic ARRAY_DEFINE(dict_drivers, struct dict *);
dce5a2719df4fc64a8762d2aa94ba98dcf9cd6feTimo Sirainen
e54512a5189192fe72d1e2c53927c98c5ac920b4Timo Sirainenstatic struct dict *dict_driver_lookup(const char *name)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen struct dict *const *dicts;
645f258ea29afaf09b673fc65d1bd788dfec8db8Timo Sirainen
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen array_foreach(&dict_drivers, dicts) {
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen struct dict *dict = *dicts;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen if (strcmp(dict->name, name) == 0)
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen return dict;
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen }
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen return NULL;
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen}
043c8a96a035379bcba04f487d58457beefdfcaaTimo Sirainen
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainenvoid dict_driver_register(struct dict *driver)
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen{
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen if (!array_is_created(&dict_drivers))
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen i_array_init(&dict_drivers, 8);
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (dict_driver_lookup(driver->name) != NULL) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen i_fatal("dict_driver_register(%s): Already registered",
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen driver->name);
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen }
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen array_append(&dict_drivers, &driver, 1);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainenvoid dict_driver_unregister(struct dict *driver)
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen{
b88c43d09a288e99d439c78de4cc613212ea924cTimo Sirainen struct dict *const *dicts;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen unsigned int idx = -1U;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen array_foreach(&dict_drivers, dicts) {
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen if (*dicts == driver) {
8fb1e3e2349c9940732b5bb77a2a4053b8f72a4fTimo Sirainen idx = array_foreach_idx(&dict_drivers, dicts);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen break;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen i_assert(idx != -1U);
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen array_delete(&dict_drivers, idx, 1);
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen
b88c43d09a288e99d439c78de4cc613212ea924cTimo Sirainen if (array_count(&dict_drivers) == 0)
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen array_free(&dict_drivers);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainenvoid dict_drivers_register_builtin(void)
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen{
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen dict_driver_register(&dict_driver_client);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen dict_driver_register(&dict_driver_file);
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen dict_driver_register(&dict_driver_redis);
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen}
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainenvoid dict_drivers_unregister_builtin(void)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen dict_driver_unregister(&dict_driver_client);
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen dict_driver_unregister(&dict_driver_file);
5cda0bfea032000c4a51134c748d9efe6614870bTimo Sirainen dict_driver_unregister(&dict_driver_redis);
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstruct dict *dict_init(const char *uri, enum dict_data_type value_type,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen const char *username, const char *base_dir)
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen{
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen struct dict *dict;
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen const char *p, *name;
8b12e7b44abca3bd51a1c46e19ca504f3b55e723Timo Sirainen
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen i_assert(username != NULL);
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen p = strchr(uri, ':');
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen if (p == NULL) {
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen i_error("Dictionary URI is missing ':': %s", uri);
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen return NULL;
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen }
8b12e7b44abca3bd51a1c46e19ca504f3b55e723Timo Sirainen
8b12e7b44abca3bd51a1c46e19ca504f3b55e723Timo Sirainen T_BEGIN {
8b12e7b44abca3bd51a1c46e19ca504f3b55e723Timo Sirainen name = t_strdup_until(uri, p);
8b12e7b44abca3bd51a1c46e19ca504f3b55e723Timo Sirainen dict = dict_driver_lookup(name);
8b12e7b44abca3bd51a1c46e19ca504f3b55e723Timo Sirainen if (dict == NULL)
8b12e7b44abca3bd51a1c46e19ca504f3b55e723Timo Sirainen i_error("Unknown dict module: %s", name);
872b8fd8a8db97dc54067b7ab25bda96ec0aac0dTimo Sirainen } T_END;
872b8fd8a8db97dc54067b7ab25bda96ec0aac0dTimo Sirainen
872b8fd8a8db97dc54067b7ab25bda96ec0aac0dTimo Sirainen return dict == NULL ? NULL :
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen dict->v.init(dict, p+1, value_type, username, base_dir);
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenvoid dict_deinit(struct dict **_dict)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen struct dict *dict = *_dict;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen *_dict = NULL;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen dict->v.deinit(dict);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenint dict_wait(struct dict *dict)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return dict->v.wait == NULL ? 1 : dict->v.wait(dict);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainenstatic bool dict_key_prefix_is_valid(const char *key)
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return strncmp(key, DICT_PATH_SHARED, strlen(DICT_PATH_SHARED)) == 0 ||
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen strncmp(key, DICT_PATH_PRIVATE, strlen(DICT_PATH_PRIVATE)) == 0;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenint dict_lookup(struct dict *dict, pool_t pool, const char *key,
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen const char **value_r)
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen i_assert(dict_key_prefix_is_valid(key));
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return dict->v.lookup(dict, pool, key, value_r);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainenstruct dict_iterate_context *
5cda0bfea032000c4a51134c748d9efe6614870bTimo Sirainendict_iterate_init(struct dict *dict, const char *path,
b88c43d09a288e99d439c78de4cc613212ea924cTimo Sirainen enum dict_iterate_flags flags)
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen{
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen const char *paths[2];
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen paths[0] = path;
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen paths[1] = NULL;
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen return dict_iterate_init_multiple(dict, paths, flags);
2aecf7be5834e7f6520f8deaad683a6fa1de4d61Timo Sirainen}
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainenstruct dict_iterate_context *
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainendict_iterate_init_multiple(struct dict *dict, const char *const *paths,
2aecf7be5834e7f6520f8deaad683a6fa1de4d61Timo Sirainen enum dict_iterate_flags flags)
2aecf7be5834e7f6520f8deaad683a6fa1de4d61Timo Sirainen{
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen unsigned int i;
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen
70612e07102b75a8511aa7f9de60771176b18de0Timo Sirainen i_assert(paths[0] != NULL);
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen for (i = 0; paths[i] != NULL; i++)
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen i_assert(dict_key_prefix_is_valid(paths[i]));
55773f17bccf6361d6599ffcbe072d7c9fe205bfTimo Sirainen return dict->v.iterate_init(dict, paths, flags);
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen}
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen
55773f17bccf6361d6599ffcbe072d7c9fe205bfTimo Sirainenbool dict_iterate(struct dict_iterate_context *ctx,
5df33e9ee65eec194105b338c55dedbf8422f695Timo Sirainen const char **key_r, const char **value_r)
55773f17bccf6361d6599ffcbe072d7c9fe205bfTimo Sirainen{
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch return ctx->dict->v.iterate(ctx, key_r, value_r);
5df33e9ee65eec194105b338c55dedbf8422f695Timo Sirainen}
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainenint dict_iterate_deinit(struct dict_iterate_context **_ctx)
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen{
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen struct dict_iterate_context *ctx = *_ctx;
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen
55773f17bccf6361d6599ffcbe072d7c9fe205bfTimo Sirainen *_ctx = NULL;
55773f17bccf6361d6599ffcbe072d7c9fe205bfTimo Sirainen return ctx->dict->v.iterate_deinit(ctx);
55773f17bccf6361d6599ffcbe072d7c9fe205bfTimo Sirainen}
77af0bd168cf3e3ddc3ae68abc82bfad7e9b5ff4Timo Sirainen
77af0bd168cf3e3ddc3ae68abc82bfad7e9b5ff4Timo Sirainenstruct dict_transaction_context *dict_transaction_begin(struct dict *dict)
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen{
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen return dict->v.transaction_init(dict);
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen}
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainenint dict_transaction_commit(struct dict_transaction_context **_ctx)
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen{
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen struct dict_transaction_context *ctx = *_ctx;
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen
77af0bd168cf3e3ddc3ae68abc82bfad7e9b5ff4Timo Sirainen *_ctx = NULL;
77af0bd168cf3e3ddc3ae68abc82bfad7e9b5ff4Timo Sirainen return ctx->dict->v.transaction_commit(ctx, FALSE, NULL, NULL);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen}
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainenvoid dict_transaction_commit_async(struct dict_transaction_context **_ctx,
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen dict_transaction_commit_callback_t *callback,
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen void *context)
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen{
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen struct dict_transaction_context *ctx = *_ctx;
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen *_ctx = NULL;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen ctx->dict->v.transaction_commit(ctx, TRUE, callback, context);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen}
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainenvoid dict_transaction_rollback(struct dict_transaction_context **_ctx)
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen{
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen struct dict_transaction_context *ctx = *_ctx;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen *_ctx = NULL;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen ctx->dict->v.transaction_rollback(ctx);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen}
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainenvoid dict_set(struct dict_transaction_context *ctx,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen const char *key, const char *value)
a4f09749814b93e8ad3ec8a0dc18885b874d6f8cTimo Sirainen{
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen i_assert(dict_key_prefix_is_valid(key));
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen ctx->dict->v.set(ctx, key, value);
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen ctx->changed = TRUE;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenvoid dict_unset(struct dict_transaction_context *ctx,
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen const char *key)
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen{
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen i_assert(dict_key_prefix_is_valid(key));
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen ctx->dict->v.unset(ctx, key);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen ctx->changed = TRUE;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainenvoid dict_atomic_inc(struct dict_transaction_context *ctx,
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen const char *key, long long diff)
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen{
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen i_assert(dict_key_prefix_is_valid(key));
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen if (diff != 0) {
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen ctx->dict->v.atomic_inc(ctx, key, diff);
1952eb389b8aba39195380970f905dcebea38dfcTimo Sirainen ctx->changed = TRUE;
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen }
86ad841251a38aa9ffcf4db4ee2c9fd449121bcbTimo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainenconst char *dict_escape_string(const char *str)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen const char *p;
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen string_t *ret;
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* see if we need to escape it */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen for (p = str; *p != '\0'; p++) {
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen if (*p == '/' || *p == '\\')
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen break;
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen if (*p == '\0')
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen return str;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen /* escape */
55773f17bccf6361d6599ffcbe072d7c9fe205bfTimo Sirainen ret = t_str_new((size_t) (p - str) + 128);
45b2a27617d8475f71fdfc870690e46cd63849f2Timo Sirainen str_append_n(ret, str, (size_t) (p - str));
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen for (; *p != '\0'; p++) {
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen switch (*p) {
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen case '/':
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen str_append_c(ret, '\\');
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen str_append_c(ret, '|');
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen break;
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen case '\\':
d22301419109ed4a38351715e6760011421dadecTimo Sirainen str_append_c(ret, '\\');
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen str_append_c(ret, '\\');
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen break;
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen default:
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen str_append_c(ret, *p);
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen break;
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen }
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen }
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen return str_c(ret);
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen}
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainenconst char *dict_unescape_string(const char *str)
e217d6fce33746e198ecc21bff0bc658664c9ef4Timo Sirainen{
70612e07102b75a8511aa7f9de60771176b18de0Timo Sirainen const char *p;
70612e07102b75a8511aa7f9de60771176b18de0Timo Sirainen string_t *ret;
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen /* see if we need to unescape it */
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen for (p = str; *p != '\0'; p++) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (*p == '\\')
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen break;
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen }
469a6cf705835ade57dcb59979b6e054207ae5d7Timo Sirainen
469a6cf705835ade57dcb59979b6e054207ae5d7Timo Sirainen if (*p == '\0')
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return str;
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen
5f44975ec6c5755dd74bcd4c47a123a7242ecab3Timo Sirainen /* unescape */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen ret = t_str_new((size_t) (p - str) + strlen(p) + 1);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen str_append_n(ret, str, (size_t) (p - str));
644268f7848a7c4221146d0b11feb8ed5bbed233Timo Sirainen
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen for (; *p != '\0'; p++) {
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen if (*p != '\\')
469a6cf705835ade57dcb59979b6e054207ae5d7Timo Sirainen str_append_c(ret, *p);
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen else {
ae1b268ffff743ad9927c304a1344c5cbd7f909dTimo Sirainen if (*++p == '|')
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen str_append_c(ret, '/');
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen else if (*p == '\0')
d2b94d25f842cd1b7acaf4dd7de858f7c6a821c9Timo Sirainen break;
d2b94d25f842cd1b7acaf4dd7de858f7c6a821c9Timo Sirainen else
d2b94d25f842cd1b7acaf4dd7de858f7c6a821c9Timo Sirainen str_append_c(ret, *p);
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen }
d22301419109ed4a38351715e6760011421dadecTimo Sirainen }
1bdda5c0c30463160c47151537e6bb2c6c994841Timo Sirainen return str_c(ret);
cf52b37d807553e91a2d6fb7cb2c8b4c34589e1dTimo Sirainen}
38d7db318188c4ac9cdc8c6cdb936b36a5258e19Timo Sirainen