]> granicus.if.org Git - pgbouncer/commitdiff
full quoting for database names
authorMarko Kreen <markokr@gmail.com>
Fri, 22 Aug 2008 17:22:30 +0000 (17:22 +0000)
committerMarko Kreen <markokr@gmail.com>
Fri, 22 Aug 2008 17:22:30 +0000 (17:22 +0000)
doc/config.txt
src/loader.c

index a91fab7a5a038bb5b7319a6de80e82af523e9037..fc571e6a0e23160be2482f476f3b6efe0d911f07 100644 (file)
@@ -335,6 +335,10 @@ This contains key=value pairs where key will be taken as database name and
 value as libpq-connstring style list of key=value pairs. As actual libpq is not
 used, so not all features from libpq can be used (service=, quoting).
 
+Database name can contain characters [0-9A-Za-z_.-] without quoting.
+Names that contain other chars need to be quoted with standard SQL
+ident quoting: double quotes where "" is taken as single quote.
+
 === Location parameters ===
 
 ==== dbname ====
index b0b58e6ba3d8cc1f4432c64d30ac1b2d4e18a4c7..93ad2b9f1a5f365b1b8ec64f8c863fc51fa4617b 100644 (file)
@@ -497,7 +497,7 @@ bool load_auth_file(const char *fn)
 }
 
 /*
- * INI file parser
+ * Config parameter handling.
  */
 
 bool cf_set_int(ConfElem *elem, const char *val, PgSocket *console)
@@ -617,12 +617,48 @@ static ConfSection *find_section(ConfSection *sect, const char *name)
        return NULL;
 }
 
+/*
+ * INI file parser.
+ */
+
+static int count_lines(const char *s, const char *end)
+{
+       int lineno = 1;
+       for (; s < end; s++) {
+               if (*s == '\n')
+                       lineno++;
+       }
+       return lineno;
+}
+
+static bool unquote_ident(char **src_p, char *dst, int dstlen)
+{
+       char *src = *src_p;
+       char *end = dst + dstlen;
+       if (*src++ != '"')
+               return false;
+       while (*src && dst < end) {
+               if (src[0] == '"') {
+                       if (src[1] != '"')
+                               break;
+                       src++;
+               }
+               *dst++ = *src++;
+       }
+       if (*src != '"' || dst >= end)
+               return false;
+       *dst = 0;
+       *src_p = src + 1;
+       return true;
+}
+
 bool iniparser(const char *fn, ConfSection *sect_list, bool reload)
 {
        char *buf;
        char *p, *key, *val;
        int klen, vlen;
        ConfSection *cur_section = NULL;
+       char keybuf[MAX_DBNAME*2];
 
        buf = load_file(fn);
        if (buf == NULL) {
@@ -646,11 +682,8 @@ bool iniparser(const char *fn, ConfSection *sect_list, bool reload)
                if (*p == '[') {
                        key = ++p;
                        while (*p && *p != ']' && *p != '\n') p++;
-                       if (*p != ']') {
-                               log_warning("bad section header");
-                               cur_section = NULL;
-                               continue;
-                       }
+                       if (*p != ']')
+                               goto syntax_error;
                        *p++ = 0;
 
                        cur_section = find_section(sect_list, key);
@@ -661,15 +694,21 @@ bool iniparser(const char *fn, ConfSection *sect_list, bool reload)
                if (*p == 0) break;
 
                /* read key val */
-               key = p;
-               while (*p && (isalnum(*p) || *p == '_')) p++;
-               klen = p - key;
+               if (*p == '"') {
+                       if (!unquote_ident(&p, keybuf, sizeof(keybuf)))
+                               goto syntax_error;
+                       key = keybuf;
+                       klen = strlen(keybuf);
+               } else {
+                       key = p;
+                       while (*p && (isalnum(*p) || strchr("_.-", *p))) p++;
+                       klen = p - key;
+               }
 
                /* expect '=', skip it */
                while (*p && (*p == ' ' || *p == '\t')) p++;
                if (*p != '=') {
-                       log_error("syntax error in configuration, stopping loading");
-                       break;
+                       goto syntax_error;
                } else
                        p++;
                while (*p && (*p == ' ' || *p == '\t')) p++;
@@ -694,5 +733,10 @@ bool iniparser(const char *fn, ConfSection *sect_list, bool reload)
 
        free(buf);
        return true;
+
+syntax_error:
+       log_error("syntax error in configuration (%s:%d), stopping loading", fn, count_lines(buf, p));
+       free(buf);
+       return true;
 }