]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-settings: Remove legacy API
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Tue, 26 Nov 2024 14:07:50 +0000 (16:07 +0200)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Fri, 17 Jan 2025 08:40:01 +0000 (10:40 +0200)
src/lib-settings/Makefile.am
src/lib-settings/settings-legacy.c [deleted file]
src/lib-settings/settings-legacy.h [deleted file]
src/lib-settings/test-settings.c

index a693f300e13b3a794da2f4b776bf167f258f965b..ae01131cb91d20d2f53ab87e61c890a27e6b3602 100644 (file)
@@ -7,12 +7,10 @@ AM_CPPFLAGS = \
 
 libsettings_la_SOURCES = \
        settings.c \
-       settings-legacy.c \
        settings-parser.c
 
 headers = \
        settings.h \
-       settings-legacy.h \
        settings-parser.h
 
 pkginc_libdir=$(pkgincludedir)
diff --git a/src/lib-settings/settings-legacy.c b/src/lib-settings/settings-legacy.c
deleted file mode 100644 (file)
index 1d87ae6..0000000
+++ /dev/null
@@ -1,434 +0,0 @@
-/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
-
-#include "lib.h"
-#include "str.h"
-#include "istream.h"
-#include "strescape.h"
-#include "settings-legacy.h"
-
-#include <stdio.h>
-#include <fcntl.h>
-#ifdef HAVE_GLOB_H
-#  include <glob.h>
-#endif
-
-#ifndef GLOB_BRACE
-#  define GLOB_BRACE 0
-#endif
-
-#define SECTION_ERRORMSG "%s (section changed in %s at line %d)"
-
-struct input_stack {
-       struct input_stack *prev;
-
-       struct istream *input;
-       const char *path;
-       unsigned int linenum;
-};
-
-settings_section_callback_t *null_settings_section_callback = NULL;
-
-static const char *get_bool(const char *value, bool *result)
-{
-       if (strcasecmp(value, "yes") == 0)
-               *result = TRUE;
-       else if (strcasecmp(value, "no") == 0)
-               *result = FALSE;
-       else
-               return t_strconcat("Invalid boolean: ", value, NULL);
-
-       return NULL;
-}
-
-static const char *get_uint(const char *value, unsigned int *result)
-{
-       int num;
-
-       if (sscanf(value, "%i", &num) != 1 || num < 0)
-               return t_strconcat("Invalid number: ", value, NULL);
-       *result = num;
-       return NULL;
-}
-
-#define IS_WHITE(c) ((c) == ' ' || (c) == '\t')
-
-static const char *expand_environment_vars(const char *value)
-{
-       const char *pvalue = value, *p;
-
-       /* Fast path when there are no candidates */
-       if ((pvalue = strchr(pvalue, '$')) == NULL)
-               return value;
-
-       string_t *expanded_value = t_str_new(strlen(value));
-       str_append_data(expanded_value, value, pvalue - value);
-
-       while (pvalue != NULL && (p = strchr(pvalue, '$')) != NULL) {
-               const char *var_end;
-               str_append_data(expanded_value, pvalue, p - pvalue);
-               if ((p == value || IS_WHITE(p[-1])) &&
-                   str_begins_with(p, "$ENV:")) {
-                       const char *var_name, *envval;
-                       var_end = strchr(p, ' ');
-                       if (var_end == NULL)
-                               var_name = p + 5;
-                       else
-                               var_name = t_strdup_until(p + 5, var_end);
-                       if ((envval = getenv(var_name)) != NULL)
-                               str_append(expanded_value, envval);
-               } else {
-                       str_append_c(expanded_value, '$');
-                       var_end = p + 1;
-               }
-               pvalue = var_end;
-       }
-
-       if (pvalue != NULL)
-               str_append(expanded_value, pvalue);
-
-       return str_c(expanded_value);
-}
-
-const char *
-parse_setting_from_defs(pool_t pool, const struct setting_def *defs, void *base,
-                       const char *key, const char *value)
-{
-       const struct setting_def *def;
-
-       for (def = defs; def->name != NULL; def++) {
-               if (strcmp(def->name, key) == 0) {
-                       void *ptr = PTR_OFFSET(base, def->offset);
-
-                       switch (def->type) {
-                       case SET_LEGACY_STR:
-                               *((char **)ptr) = p_strdup(pool, value);
-                               return NULL;
-                       case SET_LEGACY_INT:
-                               /* use %i so we can handle eg. 0600
-                                  as octal value with umasks */
-                               return get_uint(value, (unsigned int *) ptr);
-                       case SET_LEGACY_BOOL:
-                               return get_bool(value, (bool *) ptr);
-                       }
-               }
-       }
-
-       return t_strconcat("Unknown setting: ", key, NULL);
-}
-
-static const char *
-fix_relative_path(const char *path, struct input_stack *input)
-{
-       const char *p;
-
-       if (*path == '/')
-               return path;
-
-       p = strrchr(input->path, '/');
-       if (p == NULL)
-               return path;
-
-       return t_strconcat(t_strdup_until(input->path, p+1), path, NULL);
-}
-
-static int settings_add_include(const char *path, struct input_stack **inputp,
-                               bool ignore_errors, const char **error_r)
-{
-       struct input_stack *tmp, *new_input;
-       int fd;
-
-       for (tmp = *inputp; tmp != NULL; tmp = tmp->prev) {
-               if (strcmp(tmp->path, path) == 0)
-                       break;
-       }
-       if (tmp != NULL) {
-               *error_r = t_strdup_printf("Recursive include file: %s", path);
-               return -1;
-       }
-
-       if ((fd = open(path, O_RDONLY)) == -1) {
-               if (ignore_errors)
-                       return 0;
-
-               *error_r = t_strdup_printf("Couldn't open include file %s: %m",
-                                          path);
-               return -1;
-       }
-
-       new_input = t_new(struct input_stack, 1);
-       new_input->prev = *inputp;
-       new_input->path = t_strdup(path);
-       new_input->input = i_stream_create_fd_autoclose(&fd, SIZE_MAX);
-       i_stream_set_return_partial_line(new_input->input, TRUE);
-       *inputp = new_input;
-       return 0;
-}
-
-static int
-settings_include(const char *pattern, struct input_stack **inputp,
-                bool ignore_errors, const char **error_r)
-{
-#ifdef HAVE_GLOB
-       glob_t globbers;
-       unsigned int i;
-
-       switch (glob(pattern, GLOB_BRACE, NULL, &globbers)) {
-       case 0:
-               break;
-       case GLOB_NOSPACE:
-               *error_r = "glob() failed: Not enough memory";
-               return -1;
-       case GLOB_ABORTED:
-               *error_r = "glob() failed: Read error";
-               return -1;
-       case GLOB_NOMATCH:
-               if (ignore_errors)
-                       return 0;
-               *error_r = "No matches";
-               return -1;
-       default:
-               *error_r = "glob() failed: Unknown error";
-               return -1;
-       }
-
-       /* iterate through the different files matching the globbing */
-       for (i = 0; i < globbers.gl_pathc; i++) {
-               if (settings_add_include(globbers.gl_pathv[i], inputp,
-                                        ignore_errors, error_r) < 0)
-                       return -1;
-       }
-       globfree(&globbers);
-       return 0;
-#else
-       return settings_add_include(pattern, inputp, ignore_errors, error_r);
-#endif
-}
-
-bool settings_read_i(const char *path, const char *section,
-                    settings_callback_t *callback,
-                    settings_section_callback_t *sect_callback, void *context,
-                    const char **error_r)
-{
-       /* pretty horrible code, but v2.0 will have this rewritten anyway.. */
-       struct input_stack root, *input;
-       const char *errormsg, *next_section, *name, *last_section_path = NULL;
-       char *line, *key, *p, quote;
-       string_t *full_line;
-       size_t len;
-       int fd, last_section_line = 0, skip, sections, root_section;
-
-       fd = open(path, O_RDONLY);
-       if (fd < 0) {
-               *error_r = t_strdup_printf(
-                       "Can't open configuration file %s: %m", path);
-               return FALSE;
-       }
-
-       if (section == NULL) {
-               skip = 0;
-                next_section = NULL;
-       } else {
-               skip = 1;
-               next_section = t_strcut(section, '/');
-       }
-
-       i_zero(&root);
-       root.path = path;
-       input = &root;
-
-       full_line = t_str_new(512);
-       sections = 0; root_section = 0; errormsg = NULL;
-       input->input = i_stream_create_fd_autoclose(&fd, SIZE_MAX);
-       i_stream_set_return_partial_line(input->input, TRUE);
-prevfile:
-       while ((line = i_stream_read_next_line(input->input)) != NULL) {
-               input->linenum++;
-
-               /* @UNSAFE: line is modified */
-
-               /* skip whitespace */
-               while (IS_WHITE(*line))
-                       line++;
-
-               /* ignore comments or empty lines */
-               if (*line == '#' || *line == '\0')
-                       continue;
-
-               /* strip away comments. pretty kludgy way really.. */
-               for (p = line; *p != '\0'; p++) {
-                       if (*p == '\'' || *p == '"') {
-                               quote = *p;
-                               for (p++; *p != quote && *p != '\0'; p++) {
-                                       if (*p == '\\' && p[1] != '\0')
-                                               p++;
-                               }
-                               if (*p == '\0')
-                                       break;
-                       } else if (*p == '#') {
-                               if (!IS_WHITE(p[-1])) {
-                                       i_warning("Configuration file %s line %u: "
-                                                 "Ambiguous '#' character in line, treating it as comment. "
-                                                 "Add a space before it to remove this warning.",
-                                                 input->path, input->linenum);
-                               }
-                               *p = '\0';
-                               break;
-                       }
-               }
-
-               /* remove whitespace from end of line */
-               len = strlen(line);
-               while (IS_WHITE(line[len-1]))
-                       len--;
-               line[len] = '\0';
-
-               if (len > 0 && line[len-1] == '\\') {
-                       /* continues in next line */
-                       len--;
-                       while (IS_WHITE(line[len-1]))
-                               len--;
-                       str_append_data(full_line, line, len);
-                       str_append_c(full_line, ' ');
-                       continue;
-               }
-               if (str_len(full_line) > 0) {
-                       str_append(full_line, line);
-                       line = str_c_modifiable(full_line);
-               }
-
-               bool quoted = FALSE;
-               /* a) key = value
-                  b) section_type [section_name] {
-                  c) } */
-               key = line;
-               while (!IS_WHITE(*line) && *line != '\0' && *line != '=')
-                       line++;
-               if (IS_WHITE(*line)) {
-                       *line++ = '\0';
-                       while (IS_WHITE(*line)) line++;
-               }
-
-               if (strcmp(key, "!include_try") == 0 ||
-                   strcmp(key, "!include") == 0) {
-                       if (settings_include(fix_relative_path(line, input),
-                                            &input,
-                                            strcmp(key, "!include_try") == 0,
-                                            &errormsg) == 0)
-                               goto prevfile;
-               } else if (*line == '=') {
-                       /* a) */
-                       *line++ = '\0';
-                       while (IS_WHITE(*line)) line++;
-
-                       len = strlen(line);
-                       if (len > 0 &&
-                           ((*line == '"' && line[len-1] == '"') ||
-                            (*line == '\'' && line[len-1] == '\''))) {
-                               line[len-1] = '\0';
-                               line = str_unescape(line+1);
-                               quoted = TRUE;
-                       }
-
-                       /* @UNSAFE: Cast to modifiable datastack value,
-                          but it will not be actually modified after this. */
-                       if (!quoted)
-                               line = (char *)expand_environment_vars(line);
-
-                       errormsg = skip > 0 ? NULL :
-                               callback(key, line, context);
-               } else if (strcmp(key, "}") != 0 || *line != '\0') {
-                       /* b) + errors */
-                       line[-1] = '\0';
-
-                       if (*line == '{')
-                               name = "";
-                       else {
-                               name = line;
-                               while (!IS_WHITE(*line) && *line != '\0')
-                                       line++;
-
-                               if (*line != '\0') {
-                                       *line++ = '\0';
-                                       while (IS_WHITE(*line))
-                                               line++;
-                               }
-                       }
-
-                       if (*line != '{')
-                               errormsg = "Expecting '='";
-                       else {
-                               sections++;
-                               if (next_section != NULL &&
-                                   strcmp(next_section, name) == 0) {
-                                       section += strlen(next_section);
-                                       if (*section == '\0') {
-                                               skip = 0;
-                                               next_section = NULL;
-                                               root_section = sections;
-                                       } else {
-                                               i_assert(*section == '/');
-                                               section++;
-                                               next_section =
-                                                       t_strcut(section, '/');
-                                       }
-                               }
-
-                               if (skip > 0)
-                                       skip++;
-                               else {
-                                       skip = sect_callback == NULL ? 1 :
-                                               !sect_callback(key, name,
-                                                              context,
-                                                              &errormsg);
-                                       if (errormsg != NULL &&
-                                           last_section_line != 0) {
-                                               errormsg = t_strdup_printf(
-                                                       SECTION_ERRORMSG,
-                                                       errormsg,
-                                                       last_section_path,
-                                                       last_section_line);
-                                       }
-                               }
-                               last_section_path = input->path;
-                               last_section_line = input->linenum;
-                       }
-               } else {
-                       /* c) */
-                       if (sections == 0)
-                               errormsg = "Unexpected '}'";
-                       else {
-                               if (skip > 0)
-                                       skip--;
-                               else {
-                                       i_assert(sect_callback != NULL);
-                                       sect_callback(NULL, NULL, context,
-                                                     &errormsg);
-                                       if (root_section == sections &&
-                                           errormsg == NULL) {
-                                               /* we found the section,
-                                                  now quit */
-                                               break;
-                                       }
-                               }
-                               last_section_path = input->path;
-                               last_section_line = input->linenum;
-                               sections--;
-                       }
-               }
-
-               if (errormsg != NULL) {
-                       *error_r = t_strdup_printf(
-                               "Error in configuration file %s line %d: %s",
-                               input->path, input->linenum, errormsg);
-                       break;
-               }
-               str_truncate(full_line, 0);
-       }
-
-       i_stream_destroy(&input->input);
-       input = input->prev;
-       if (line == NULL && input != NULL)
-               goto prevfile;
-
-       return errormsg == NULL;
-}
diff --git a/src/lib-settings/settings-legacy.h b/src/lib-settings/settings-legacy.h
deleted file mode 100644 (file)
index 66c83b4..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-#ifndef SETTINGS_LEGACY_H
-#define SETTINGS_LEGACY_H
-
-/*
- * Note:
- *
- * The definitions in this file are used for parsing of external config
- * files and *not* for parsing of dovecot.conf.  Unfortunately, the types
- * here (e.g., enum settings_type) collide with those in settings-parser.h.
- *
- * We should remove the need for this file in v3.0.
- */
-
-enum setting_legacy_type {
-       SET_LEGACY_STR,
-       SET_LEGACY_INT,
-       SET_LEGACY_BOOL
-};
-
-struct setting_def {
-       enum setting_legacy_type type;
-       const char *name;
-       size_t offset;
-};
-
-#define DEF_STRUCT_STR(name, struct_name) \
-       { SET_LEGACY_STR + COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE( \
-               ((struct struct_name *)0)->name, const char *), \
-         #name, offsetof(struct struct_name, name) }
-#define DEF_STRUCT_INT(name, struct_name) \
-       { SET_LEGACY_INT + COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE( \
-               ((struct struct_name *)0)->name, unsigned int), \
-         #name, offsetof(struct struct_name, name) }
-#define DEF_STRUCT_BOOL(name, struct_name) \
-       { SET_LEGACY_BOOL + COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE( \
-               ((struct struct_name *)0)->name, bool), \
-         #name, offsetof(struct struct_name, name) }
-
-/* Return error message. When closing section, key = NULL, value = NULL. */
-typedef const char *settings_callback_t(const char *key, const char *value,
-                                       void *context);
-
-/* Return TRUE if we want to go inside the section */
-typedef bool settings_section_callback_t(const char *type, const char *name,
-                                        void *context, const char **errormsg);
-
-extern settings_section_callback_t *null_settings_section_callback;
-
-const char *
-parse_setting_from_defs(pool_t pool, const struct setting_def *defs, void *base,
-                       const char *key, const char *value);
-
-bool settings_read_i(const char *path, const char *section,
-                    settings_callback_t *callback,
-                    settings_section_callback_t *sect_callback, void *context,
-                    const char **error_r)
-       ATTR_NULL(2, 4, 5);
-#define settings_read(path, section, callback, sect_callback, context, error_r) \
-         settings_read_i(path - \
-               CALLBACK_TYPECHECK(callback, const char *(*)( \
-                       const char *, const char *, typeof(context))) - \
-               CALLBACK_TYPECHECK(sect_callback, bool (*)( \
-                       const char *, const char *, typeof(context), \
-                       const char **)), \
-               section, (settings_callback_t *)callback, \
-               (settings_section_callback_t *)sect_callback, context, error_r)
-#define settings_read_nosection(path, callback, context, error_r) \
-         settings_read_i(path - \
-               CALLBACK_TYPECHECK(callback, const char *(*)( \
-                       const char *, const char *, typeof(context))), \
-               NULL, (settings_callback_t *)callback, NULL, context, error_r)
-
-#endif
index fb1efb79f713af0af246b812c0ddd459e9aebaec..1d56dce3a89f718fe171b2a245ca586dfa1aebc6 100644 (file)
@@ -2,164 +2,9 @@
 
 #include "lib.h"
 #include "array.h"
-#include "net.h"
 #include "settings.h"
-#include "settings-legacy.h"
-#include "istream.h"
-#include "ostream.h"
 #include "test-common.h"
 
-/*
- * settings_read_nosection()
- */
-
-#define TEST_SETTING_FILE ".test_settings.conf"
-
-static const char *config_contents =
-"# this is a comment\n"
-"str = value\n"
-"str2 = some other value # and this should be ignored\n"
-"str3 = $ENV:test\n"
-"str4 = $ENV:test %{second}\n"
-"str5 = Hello $ENV:test\n"
-"str6 = foo$ENV:test bar\n"
-"str7 = \"this is $ENV:test string literal\"\n"
-"str8 = \\$ENV:test escaped\n"
-"str9 = $ENV:FOO$ENV:FOO bar\n"
-"str10 = \\$escape \\escape \\\"escape\\\"\n"
-"str11 = 'this is $ENV:test string literal'\n"
-"str12 = $ENV:test $ENV:test\n"
-"b_true = yes\n"
-"b_false = no\n"
-"number = 1234\n";
-
-struct test_settings {
-       const char *str;
-       const char *str2;
-       const char *str3;
-       const char *str4;
-       const char *str5;
-       const char *str6;
-       const char *str7;
-       const char *str8;
-       const char *str9;
-       const char *str10;
-       const char *str11;
-       const char *str12;
-
-       bool b_true;
-       bool b_false;
-       unsigned int number;
-};
-
-#undef DEF_STR
-#undef DEF_BOOL
-#undef DEF_INT
-
-#define DEF_STR(name) DEF_STRUCT_STR(name, test_settings)
-#define DEF_BOOL(name) DEF_STRUCT_BOOL(name, test_settings)
-#define DEF_INT(name) DEF_STRUCT_INT(name, test_settings)
-
-static struct setting_def setting_defs[] = {
-       DEF_STR(str),
-       DEF_STR(str2),
-       DEF_STR(str3),
-       DEF_STR(str4),
-       DEF_STR(str5),
-       DEF_STR(str6),
-       DEF_STR(str7),
-       DEF_STR(str8),
-       DEF_STR(str9),
-       DEF_STR(str10),
-       DEF_STR(str11),
-       DEF_STR(str12),
-       DEF_BOOL(b_true),
-       DEF_BOOL(b_false),
-       DEF_INT(number),
-       { 0, NULL, 0 }
-};
-
-static struct test_settings default_settings = {
-       .str   = "",
-       .str2  = "",
-       .str3  = "",
-       .str4  = "",
-       .str5  = "",
-       .str6  = "",
-       .str7  = "",
-       .str8  = "",
-       .str9  = "",
-       .str10 = "",
-       .str11 = "",
-       .str12 = "",
-
-       .b_true = FALSE,
-       .b_false = TRUE,
-       .number = 0,
-};
-
-struct test_settings_context {
-       pool_t pool;
-       struct test_settings set;
-};
-
-static const char *parse_setting(const char *key, const char *value,
-                                struct test_settings_context *ctx)
-{
-       return parse_setting_from_defs(ctx->pool, setting_defs,
-                                      &ctx->set, key, value);
-}
-
-static void test_settings_read_nosection(void)
-{
-       test_begin("settings_read_nosection");
-
-       const char *error = NULL;
-       /* write a simple config file */
-       struct ostream *os = o_stream_create_file(TEST_SETTING_FILE, 0, 0600, 0);
-       o_stream_nsend_str(os, config_contents);
-       test_assert(o_stream_finish(os) == 1);
-       o_stream_unref(&os);
-
-       putenv("test=first");
-       putenv("FOO$ENV:FOO=works");
-       /* try parse it */
-       pool_t pool = pool_alloconly_create("test settings", 1024);
-       struct test_settings_context *ctx =
-               p_new(pool, struct test_settings_context, 1);
-       ctx->pool = pool;
-       ctx->set = default_settings;
-
-       test_assert(settings_read_nosection(TEST_SETTING_FILE, parse_setting,
-                                           ctx, &error));
-       test_assert(error == NULL);
-       if (error != NULL)
-               i_error("%s", error);
-
-       /* see what we got */
-       test_assert_strcmp(ctx->set.str, "value");
-       test_assert_strcmp(ctx->set.str2, "some other value");
-       test_assert_strcmp(ctx->set.str3, "first");
-       test_assert_strcmp(ctx->set.str4, "first %{second}");
-       test_assert_strcmp(ctx->set.str5, "Hello first");
-       test_assert_strcmp(ctx->set.str6, "foo$ENV:test bar");
-       test_assert_strcmp(ctx->set.str7, "this is $ENV:test string literal");
-       test_assert_strcmp(ctx->set.str8, "\\$ENV:test escaped");
-       test_assert_strcmp(ctx->set.str9, "works bar");
-       test_assert_strcmp(ctx->set.str10, "\\$escape \\escape \\\"escape\\\"");
-       test_assert_strcmp(ctx->set.str11, "this is $ENV:test string literal");
-       test_assert_strcmp(ctx->set.str12, "first first");
-
-       test_assert(ctx->set.b_true == TRUE);
-       test_assert(ctx->set.b_false == FALSE);
-       test_assert(ctx->set.number == 1234);
-
-       pool_unref(&pool);
-
-       i_unlink_if_exists(TEST_SETTING_FILE);
-       test_end();
-}
-
 /*
  * settings_get()
  */
@@ -408,7 +253,6 @@ static void test_settings_get(void)
 int main(void)
 {
        static void (*const test_functions[])(void) = {
-               test_settings_read_nosection,
                test_settings_get,
                NULL
        };