]> git.netwichtig.de Git - user/henk/code/exim.git/blobdiff - src/src/lookups/lf_sqlperform.c
DCC: fix loop expression
[user/henk/code/exim.git] / src / src / lookups / lf_sqlperform.c
index a58e1926c95e7447ad52bed7483341e041b5033b..38b7c2ad345c4bde4f6cbcadb74ae42994eb2f8a 100644 (file)
@@ -2,7 +2,8 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2009 */
+/* Copyright (c) University of Cambridge 1995 - 2018 */
+/* Copyright (c) The Exim Maintainers 2020 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 
 /* See the file NOTICE for conditions of use and distribution. */
 
 
@@ -27,7 +28,7 @@ Arguments:
   query          the query
   result         where to pass back the result
   errmsg         where to pass back an error message
   query          the query
   result         where to pass back the result
   errmsg         where to pass back an error message
-  do_cache       to be set FALSE if data is changed
+  do_cache       to be set zero if data is changed
   func           the lookup function to call
 
 Returns:         the return from the lookup function, or DEFER
   func           the lookup function to call
 
 Returns:         the return from the lookup function, or DEFER
@@ -36,55 +37,35 @@ Returns:         the return from the lookup function, or DEFER
 int
 lf_sqlperform(const uschar *name, const uschar *optionname,
   const uschar *optserverlist, const uschar *query,
 int
 lf_sqlperform(const uschar *name, const uschar *optionname,
   const uschar *optserverlist, const uschar *query,
-  uschar **result, uschar **errmsg, BOOL *do_cache,
-  int(*fn)(const uschar *, uschar *, uschar **, uschar **, BOOL *, BOOL *))
+  uschar **result, uschar **errmsg, uint *do_cache, const uschar * opts,
+  int(*fn)(const uschar *, uschar *, uschar **, uschar **, BOOL *, uint *, const uschar *))
 {
 {
-int sep, rc;
+int rc;
 uschar *server;
 uschar *server;
-const uschar *serverlist;
-uschar buffer[512];
 BOOL defer_break = FALSE;
 
 BOOL defer_break = FALSE;
 
-DEBUG(D_lookup) debug_printf("%s query: %s\n", name, query);
-
-/* Handle queries that do not have server information at the start. */
-
-if (Ustrncmp(query, "servers", 7) != 0)
-  {
-  sep = 0;
-  serverlist = optserverlist;
-  while ((server = string_nextinlist(&serverlist, &sep, buffer,
-          sizeof(buffer))) != NULL)
-    {
-    rc = (*fn)(query, server, result, errmsg, &defer_break, do_cache);
-    if (rc != DEFER || defer_break) return rc;
-    }
-  if (optserverlist == NULL)
-    *errmsg = string_sprintf("no %s servers defined (%s option)", name,
-      optionname);
-  }
+DEBUG(D_lookup) debug_printf_indent("%s query: \"%s\" opts '%s'\n", name, query, opts);
 
 /* Handle queries that do have server information at the start. */
 
 
 /* Handle queries that do have server information at the start. */
 
-else
+if (Ustrncmp(query, "servers", 7) == 0)
   {
   {
-  int qsep;
+  int qsep = 0;
   const uschar *s, *ss;
   const uschar *qserverlist;
   uschar *qserver;
   const uschar *s, *ss;
   const uschar *qserverlist;
   uschar *qserver;
-  uschar qbuffer[512];
 
   s = query + 7;
 
   s = query + 7;
-  while (isspace(*s)) s++;
+  skip_whitespace(&s);
   if (*s++ != '=')
     {
     *errmsg = string_sprintf("missing = after \"servers\" in %s lookup", name);
     return DEFER;
     }
   if (*s++ != '=')
     {
     *errmsg = string_sprintf("missing = after \"servers\" in %s lookup", name);
     return DEFER;
     }
-  while (isspace(*s)) s++;
+  skip_whitespace(&s);
 
   ss = Ustrchr(s, ';');
 
   ss = Ustrchr(s, ';');
-  if (ss == NULL)
+  if (!ss)
     {
     *errmsg = string_sprintf("missing ; after \"servers=\" in %s lookup",
       name);
     {
     *errmsg = string_sprintf("missing ; after \"servers=\" in %s lookup",
       name);
@@ -98,28 +79,22 @@ else
     return DEFER;
     }
 
     return DEFER;
     }
 
-  qserverlist = string_sprintf("%.*s", ss - s, s);
-  qsep = 0;
+  qserverlist = string_sprintf("%.*s", (int)(ss - s), s);
 
 
-  while ((qserver = string_nextinlist(&qserverlist, &qsep, qbuffer,
-           sizeof(qbuffer))) != NULL)
+  while ((qserver = string_nextinlist(&qserverlist, &qsep, NULL, 0)))
     {
     {
-    if (Ustrchr(qserver, '/') != NULL)
+    if (Ustrchr(qserver, '/'))
       server = qserver;
     else
       {
       int len = Ustrlen(qserver);
       server = qserver;
     else
       {
       int len = Ustrlen(qserver);
+      const uschar * serverlist = optserverlist;
 
 
-      sep = 0;
-      serverlist = optserverlist;
-      while ((server = string_nextinlist(&serverlist, &sep, buffer,
-              sizeof(buffer))) != NULL)
-        {
+      for (int sep = 0; server = string_nextinlist(&serverlist, &sep, NULL, 0);)
         if (Ustrncmp(server, qserver, len) == 0 && server[len] == '/')
           break;
         if (Ustrncmp(server, qserver, len) == 0 && server[len] == '/')
           break;
-        }
 
 
-      if (server == NULL)
+      if (!server)
         {
         *errmsg = string_sprintf("%s server \"%s\" not found in %s", name,
           qserver, optionname);
         {
         *errmsg = string_sprintf("%s server \"%s\" not found in %s", name,
           qserver, optionname);
@@ -127,11 +102,77 @@ else
         }
       }
 
         }
       }
 
-    rc = (*fn)(ss+1, server, result, errmsg, &defer_break, do_cache);
+    { uschar *m;
+    if ((m = is_tainted2(server, 0, "Tainted %s server '%s'", name, server)))
+     {
+      *errmsg = m;
+      return DEFER;
+      }
+    }
+
+    rc = (*fn)(ss+1, server, result, errmsg, &defer_break, do_cache, opts);
     if (rc != DEFER || defer_break) return rc;
     }
   }
 
     if (rc != DEFER || defer_break) return rc;
     }
   }
 
+/* Handle queries that do not have server information at the start. */
+
+else
+  {
+  const uschar * serverlist = NULL;
+
+  /* If options are present, scan for a server definition.  Default to
+  the "optserverlist" srgument. */
+
+  if (opts)
+    {
+    uschar * ele;
+    for (int sep = ','; ele = string_nextinlist(&opts, &sep, NULL, 0); )
+      if (Ustrncmp(ele, "servers=", 8) == 0)
+       { serverlist = ele + 8; break; }
+    }
+
+  if (!serverlist)
+    serverlist = optserverlist;
+  if (!serverlist)
+    *errmsg = string_sprintf("no %s servers defined (%s option)", name,
+      optionname);
+  else
+    for (int d = 0; (server = string_nextinlist(&serverlist, &d, NULL, 0)); )
+      {
+      /* If not a full spec assume from options; scan main list for matching
+      hostname */
+
+      if (!Ustrchr(server, '/'))
+       {
+       int len = Ustrlen(server);
+       const uschar * slist = optserverlist;
+       uschar * ele;
+       for (int sep = 0; ele = string_nextinlist(&slist, &sep, NULL, 0); )
+         if (Ustrncmp(ele, server, len) == 0 && ele[len] == '/')
+           break;
+       if (!ele)
+         {
+         *errmsg = string_sprintf("%s server \"%s\" not found in %s", name,
+           server, optionname);
+         return DEFER;
+         }
+       server = ele;
+       }
+
+      { uschar *m;
+      if ((m = is_tainted2(server, 0, "Tainted %s server '%s'", name, server)))
+        {
+        *errmsg = m;
+        return DEFER;
+        }
+      }
+
+      rc = (*fn)(query, server, result, errmsg, &defer_break, do_cache, opts);
+      if (rc != DEFER || defer_break) return rc;
+      }
+  }
+
 return DEFER;
 }
 
 return DEFER;
 }