Copyright updates:
[exim.git] / src / src / moan.c
index 51f5da58a28ee723f1c141815251c9e6a4469705..25595816c78628c446b82f581b0b426d7b4780a9 100644 (file)
@@ -2,8 +2,10 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
+/* Copyright (c) The Exim Maintainers 2020 - 2023 */
 /* 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 */
 
 /* Functions for sending messages to sender or to mailmaster. */
 
@@ -63,7 +65,7 @@ if (!message_id)
     if (h->type == htype_id)
       {
       message_id = Ustrchr(h->text, ':') + 1;
-      while (isspace(*message_id)) message_id++;
+      Uskip_whitespace(&message_id);
       }
 
 for (h = header_list; h; h = h->next)
@@ -78,28 +80,48 @@ if (!h)
 /* We limit the total length of references.  Although there is no fixed
 limit, some systems do not like headers growing beyond recognition.
 Keep the first message ID for the thread root and the last few for
-the position inside the thread, up to a maximum of 12 altogether. */
+the position inside the thread, up to a maximum of 12 altogether.
+Also apply the max line length limit from RFC 2822 2.1.1
+
+XXX preferably we would get any limit from the outbound transport,
+passed in here for a limit value.
+*/
 
 if (h || message_id)
   {
-  fprintf(fp, "References:");
+  unsigned use = fprintf(fp, "References:");
+  if (message_id) use += Ustrlen(message_id) + 1;
   if (h)
     {
-    uschar * s, * id, * error;
+    const uschar * s;
+    uschar * id, * error;
     uschar * referenced_ids[12];
     int reference_count = 0;
 
     s = Ustrchr(h->text, ':') + 1;
     f.parse_allow_group = FALSE;
     while (*s && (s = parse_message_id(s, &id, &error)))
-      if (reference_count == nelem(referenced_ids))
-        {
-        memmove(referenced_ids + 1, referenced_ids + 2,
-           sizeof(referenced_ids) - 2*sizeof(uschar *));
-        referenced_ids[reference_count - 1] = id;
-        }
+      {
+      unsigned this = Ustrlen(id);
+      if (  reference_count == nelem(referenced_ids)
+        || use + this + reference_count > 998
+         )
+       {
+       if (reference_count > 1)
+         {
+         /* drop position 1 and shuffle down */
+         use -= Ustrlen(referenced_ids + 1);
+         memmove(referenced_ids + 1, referenced_ids + 2,
+            sizeof(referenced_ids) - 2*sizeof(*referenced_ids));
+
+         /* append new one */
+         referenced_ids[reference_count - 1] = id;
+         }
+       }
       else
        referenced_ids[reference_count++] = id;
+      use += this;
+      }
 
     for (int i = 0; i < reference_count; ++i)
       fprintf(fp, " %s", referenced_ids[i]);
@@ -384,7 +406,7 @@ if (bounce_return_message)
   if (bounce_return_body && message_file)
     {
     BOOL enddot = f.dot_ends && message_file == stdin;
-    uschar * buf = store_get(bounce_return_linesize_limit+2, TRUE);
+    uschar * buf = store_get(bounce_return_linesize_limit+2, GET_TAINTED);
 
     if (firstline) fprintf(fp, "%s", CS firstline);
 
@@ -692,7 +714,7 @@ fprintf(stderr, "%d previous message%s successfully processed.\n",
 
 fprintf(stderr, "The rest of the batch was abandoned.\n");
 
-exim_exit(yield, US"batch");
+exim_exit(yield);
 }
 
 
@@ -717,7 +739,6 @@ moan_check_errorcopy(uschar *recipient)
 uschar *item, *localpart, *domain;
 const uschar *listptr = errors_copy;
 uschar *yield = NULL;
-uschar buffer[256];
 int sep = 0;
 int llen;
 
@@ -733,7 +754,7 @@ llen = domain++ - recipient;
 
 /* Scan through the configured items */
 
-while ((item = string_nextinlist(&listptr, &sep, buffer, sizeof(buffer))))
+while ((item = string_nextinlist(&listptr, &sep, NULL, 0)))
   {
   const uschar *newaddress = item;
   const uschar *pattern = string_dequote(&newaddress);