]> git.netwichtig.de Git - user/henk/code/exim.git/blobdiff - src/src/transport.c
Fix json extract for strings carrying commas. Bug 3006
[user/henk/code/exim.git] / src / src / transport.c
index 7477882cb9565128809f9f4ece4a2cd10efe7a24..c125cc7c3995b93beb52f1516cd2ce976ede4db5 100644 (file)
@@ -5,6 +5,7 @@
 /* Copyright (c) The Exim Maintainers 2020 - 2022 */
 /* Copyright (c) University of Cambridge 1995 - 2018 */
 /* See the file NOTICE for conditions of use and distribution. */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
 
 /* General functions concerned with transportation, and generic options for all
 transports. */
@@ -705,7 +706,7 @@ BOOL
 transport_headers_send(transport_ctx * tctx,
   BOOL (*sendfn)(transport_ctx * tctx, uschar * s, int len))
 {
-const uschar *list;
+const uschar * list;
 transport_instance * tblock = tctx ? tctx->tblock : NULL;
 address_item * addr = tctx ? tctx->addr : NULL;
 
@@ -760,15 +761,18 @@ for (header_line * h = header_list; h; h = h->next) if (h->type != htype_old)
 
   if (include_header)
     {
+    int len;
     if (tblock && tblock->rewrite_rules)
       {
       rmark reset_point = store_mark();
-      header_line *hh;
+      header_line * hh;
 
       if ((hh = rewrite_header(h, NULL, NULL, tblock->rewrite_rules,
                  tblock->rewrite_existflags, FALSE)))
        {
-       if (!sendfn(tctx, hh->text, hh->slen)) return FALSE;
+       len = hh->slen;
+       if (tctx->options & topt_truncate_headers && len > 998) len = 998;
+       if (!sendfn(tctx, hh->text, len)) return FALSE;
        store_reset(reset_point);
        continue;     /* With the next header line */
        }
@@ -776,7 +780,9 @@ for (header_line * h = header_list; h; h = h->next) if (h->type != htype_old)
 
     /* Either no rewriting rules, or it didn't get rewritten */
 
-    if (!sendfn(tctx, h->text, h->slen)) return FALSE;
+    len = h->slen;
+    if (tctx->options & topt_truncate_headers && len > 998) len = 998;
+    if (!sendfn(tctx, h->text, len)) return FALSE;
     }
 
   /* Header removed */
@@ -1037,7 +1043,7 @@ if (tctx->options & topt_use_bdat)
   if (!(tctx->options & topt_no_body))
     {
     if ((fsize = lseek(deliver_datafile, 0, SEEK_END)) < 0) return FALSE;
-    fsize -= SPOOL_DATA_START_OFFSET;
+    fsize -= spool_data_start_offset(message_id);
     if (size_limit > 0  &&  fsize > size_limit)
       fsize = size_limit;
     size = hsize + fsize;
@@ -1095,7 +1101,7 @@ if (  f.spool_file_wireformat
    )
   {
   ssize_t copied = 0;
-  off_t offset = SPOOL_DATA_START_OFFSET;
+  off_t offset = spool_data_start_offset(message_id);
 
   /* Write out any header data in the buffer */
 
@@ -1133,7 +1139,7 @@ if (!(tctx->options & topt_no_body))
 
   nl_check_length = abs(nl_check_length);
   nl_partial_match = 0;
-  if (lseek(deliver_datafile, SPOOL_DATA_START_OFFSET, SEEK_SET) < 0)
+  if (lseek(deliver_datafile, spool_data_start_offset(message_id), SEEK_SET) < 0)
     return FALSE;
   while (  (len = MIN(DELIVER_IN_BUFFER_SIZE, size)) > 0
        && (len = read(deliver_datafile, deliver_in_buffer, len)) > 0)
@@ -1491,12 +1497,19 @@ Returns:    nothing
 */
 
 void
-transport_update_waiting(host_item *hostlist, uschar *tpname)
+transport_update_waiting(host_item * hostlist, uschar * tpname)
 {
 const uschar *prevname = US"";
 open_db dbblock;
 open_db *dbm_file;
 
+if (!is_new_message_id(message_id))
+  {
+  DEBUG(D_transport) debug_printf("message_id %s is not new format; "
+    "skipping wait-%s database update\n", tpname);
+  return;
+  }
+
 DEBUG(D_transport) debug_printf("updating wait-%s database\n", tpname);
 
 /* Open the database for this transport */
@@ -1511,7 +1524,7 @@ that the message id is in each host record. */
 for (host_item * host = hostlist; host; host = host->next)
   {
   BOOL already = FALSE;
-  dbdata_wait *host_record;
+  dbdata_wait * host_record;
   int host_length;
   uschar buffer[256];
 
@@ -1537,8 +1550,27 @@ for (host_item * host = hostlist; host; host = host->next)
 
   for (uschar * s = host_record->text; s < host_record->text + host_length;
        s += MESSAGE_ID_LENGTH)
+    {
+    /* If any ID is seen which is not new-format, wipe the record and
+    any continuations */
+
+    if (!is_new_message_id(s))
+      {
+      DEBUG(D_hints_lookup)
+       debug_printf_indent("NOTE: old or corrupt message-id found in wait=%.200s"
+         " hints DB; deleting records for %s\n", tpname, host->name);
+
+      (void) dbfn_delete(dbm_file, host->name);
+      for (int i = host_record->sequence - 1; i >= 0; i--)
+       (void) dbfn_delete(dbm_file,
+                   (sprintf(CS buffer, "%.200s:%d", host->name, i), buffer));
+
+      host_record->count = host_record->sequence = 0;
+      break;
+      }
     if (Ustrncmp(s, message_id, MESSAGE_ID_LENGTH) == 0)
       { already = TRUE; break; }
+    }
 
   /* If we haven't found this message in the main record, search any
   continuation records that exist. */
@@ -1646,13 +1678,14 @@ typedef struct msgq_s
 } msgq_t;
 
 BOOL
-transport_check_waiting(const uschar *transport_name, const uschar *hostname,
-  int local_message_max, uschar *new_message_id, oicf oicf_func, void *oicf_data)
+transport_check_waiting(const uschar * transport_name, const uschar * hostname,
+  int local_message_max, uschar * new_message_id,
+  oicf oicf_func, void * oicf_data)
 {
-dbdata_wait *host_record;
+dbdata_wait * host_record;
 int host_length;
 open_db dbblock;
-open_db *dbm_file;
+open_db * dbm_file;
 
 int         i;
 struct stat statbuf;
@@ -1729,6 +1762,22 @@ while (1)
 
   for (i = 0; i < host_record->count; ++i)
     {
+    /* If any ID is seen which is not new-format, wipe the record and
+    any continuations */
+
+    if (!is_new_message_id(host_record->text + (i * MESSAGE_ID_LENGTH)))
+      {
+      uschar buffer[256];
+      DEBUG(D_hints_lookup)
+       debug_printf_indent("NOTE: old or corrupt message-id found in wait=%.200s"
+         " hints DB; deleting records for %s\n", transport_name, hostname);
+      (void) dbfn_delete(dbm_file, hostname);
+      for (int i = host_record->sequence - 1; i >= 0; i--)
+       (void) dbfn_delete(dbm_file,
+                   (sprintf(CS buffer, "%.200s:%d", hostname, i), buffer));
+      dbfn_close(dbm_file);
+      goto retfalse;
+      }
     msgq[i].bKeep = TRUE;
 
     Ustrncpy_nt(msgq[i].message_id, host_record->text + (i * MESSAGE_ID_LENGTH),
@@ -1879,8 +1928,8 @@ return FALSE;
 
 /* Just the regain-root-privilege exec portion */
 void
-transport_do_pass_socket(const uschar *transport_name, const uschar *hostname,
-  const uschar *hostaddress, uschar *id, int socket_fd)
+transport_do_pass_socket(const uschar * transport_name, const uschar * hostname,
+  const uschar * hostaddress, uschar * id, int socket_fd)
 {
 int i = 13;
 const uschar **argv;
@@ -2189,6 +2238,8 @@ if (expand_arguments)
 
   for (int i = 0; argv[i]; i++)
     {
+    DEBUG(D_expand) debug_printf_indent("arg %d\n", i);
+
     /* Handle special fudge for passing an address list */
 
     if (addr &&
@@ -2363,7 +2414,7 @@ if (expand_arguments)
         return FALSE;
         }
 
-      if ( f.running_in_test_harness && is_tainted(expanded_arg)
+      if (  f.running_in_test_harness && is_tainted(expanded_arg)
         && Ustrcmp(etext, "queryprogram router") == 0)
        {                       /* hack, would be good to not need it */
        DEBUG(D_transport)