~ubuntu-branches/ubuntu/hardy/exim4/hardy-proposed

« back to all changes in this revision

Viewing changes to src/header.c

  • Committer: Bazaar Package Importer
  • Author(s): Marc Haber
  • Date: 2005-07-02 06:08:34 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20050702060834-qk17pd52kb9nt3bj
Tags: 4.52-1
* new upstream version 4.51. (mh)
  * adapt 70_remove_exim-users_references
  * remove 37_gnutlsparams
  * adapt 36_pcre
  * adapt 31_eximmanpage
* fix package priorities to have them in sync with override again. (mh)
* Fix error in nb (Norwegian) translation.
  Thanks to Helge Hafting. (mh). Closes: #315775
* Standards-Version: 3.6.2, no changes needed. (mh)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Cambridge: exim/exim-src/src/header.c,v 1.4 2005/01/04 10:00:42 ph10 Exp $ */
 
2
 
1
3
/*************************************************
2
4
*     Exim - an Internet mail transport agent    *
3
5
*************************************************/
4
6
 
5
 
/* Copyright (c) University of Cambridge 1995 - 2004 */
 
7
/* Copyright (c) University of Cambridge 1995 - 2005 */
6
8
/* See the file NOTICE for conditions of use and distribution. */
7
9
 
8
10
 
10
12
 
11
13
 
12
14
/*************************************************
 
15
*         Test a header for matching name        *
 
16
*************************************************/
 
17
 
 
18
/* This function tests the name of a header. It is made into a function because
 
19
it isn't just a string comparison: spaces and tabs are permitted between the
 
20
name and the colon. The h->text field should nowadays never be NULL, but check
 
21
it just in case.
 
22
 
 
23
Arguments:
 
24
  h         points to the header
 
25
  name      the name to test
 
26
  len       the length of the name
 
27
  notdel    if TRUE, force FALSE for deleted headers
 
28
 
 
29
Returns:    TRUE or FALSE
 
30
*/
 
31
 
 
32
BOOL
 
33
header_testname(header_line *h, uschar *name, int len, BOOL notdel)
 
34
{
 
35
uschar *tt;
 
36
if (h->type == '*' && notdel) return FALSE;
 
37
if (h->text == NULL || strncmpic(h->text, name, len) != 0) return FALSE;
 
38
tt = h->text + len;
 
39
while (*tt == ' ' || *tt == '\t') tt++;
 
40
return *tt == ':';
 
41
}
 
42
 
 
43
/* This is a copy of the function above, only that it is possible to pass
 
44
   only the beginning of a header name. It simply does a front-anchored
 
45
   substring match. Arguments and Return codes are the same as for
 
46
   header_testname() above. */
 
47
 
 
48
BOOL
 
49
header_testname_incomplete(header_line *h, uschar *name, int len, BOOL notdel)
 
50
{
 
51
if (h->type == '*' && notdel) return FALSE;
 
52
if (h->text == NULL || strncmpic(h->text, name, len) != 0) return FALSE;
 
53
return TRUE;
 
54
}
 
55
 
 
56
 
 
57
/*************************************************
 
58
*         Add new header backend function        *
 
59
*************************************************/
 
60
 
 
61
/* The header_last variable points to the last header during message reception
 
62
and delivery; otherwise it is NULL. We add new headers only when header_last is
 
63
not NULL. The function may get called sometimes when it is NULL (e.g. during
 
64
address verification where rewriting options exist). When called from a filter,
 
65
there may be multiple header lines in a single string.
 
66
 
 
67
This is an internal static function that is the common back end to the external
 
68
functions defined below. The general interface allows the header to be inserted
 
69
before or after a given occurrence of a given header.
 
70
 
 
71
(a) if "name" is NULL, the header is added at the end of all the existing
 
72
    headers if "after" is true, or at the start if it is false. The "topnot"
 
73
    flag is not used.
 
74
 
 
75
(b) If "name" is not NULL, the first existing header with that name is sought.
 
76
    If "after" is false, the new header is added before it. If "after" is true,
 
77
    a check is made for adjacent headers with the same name, and the new header
 
78
    is added after the last of them. If a header of the given name is not
 
79
    found, the new header is added first if "topnot" is true, and at the bottom
 
80
    otherwise.
 
81
 
 
82
Arguments:
 
83
  after     TRUE for "after", FALSE for "before"
 
84
  name      name if adding at a specific header, else NULL
 
85
  topnot    TRUE to add at top if no header found
 
86
  type      Exim header type character (htype_something)
 
87
  format    sprintf format
 
88
  ap        va_list value for format arguments
 
89
 
 
90
Returns:    nothing
 
91
*/
 
92
 
 
93
static void
 
94
header_add_backend(BOOL after, uschar *name, BOOL topnot, int type,
 
95
  char *format, va_list ap)
 
96
{
 
97
header_line *h, *new;
 
98
header_line **hptr;
 
99
 
 
100
uschar *p, *q;
 
101
uschar buffer[HEADER_ADD_BUFFER_SIZE];
 
102
 
 
103
if (header_last == NULL) return;
 
104
 
 
105
if (!string_vformat(buffer, sizeof(buffer), format, ap))
 
106
  log_write(0, LOG_MAIN|LOG_PANIC_DIE, "string too long in header_add: "
 
107
    "%.100s ...", buffer);
 
108
 
 
109
/* Find where to insert this header */
 
110
 
 
111
if (name == NULL)
 
112
  {
 
113
  if (after)
 
114
    {
 
115
    hptr = &(header_last->next);
 
116
    h = NULL;
 
117
    }
 
118
  else
 
119
    {
 
120
    hptr = &header_list;
 
121
    h = header_list;
 
122
    }
 
123
  }
 
124
 
 
125
else
 
126
  {
 
127
  int len = Ustrlen(name);
 
128
 
 
129
  /* Find the first non-deleted header witht the correct name. */
 
130
 
 
131
  for (hptr = &header_list; (h = *hptr) != NULL; hptr = &(h->next))
 
132
    {
 
133
    if (header_testname(h, name, len, TRUE)) break;
 
134
    }
 
135
 
 
136
  /* Handle the case where no header is found. To insert at the bottom, nothing
 
137
  needs to be done. */
 
138
 
 
139
  if (h == NULL)
 
140
    {
 
141
    if (topnot)
 
142
      {
 
143
      hptr = &header_list;
 
144
      h = header_list;
 
145
      }
 
146
    }
 
147
 
 
148
  /* Handle the case where a header is found. Check for more if "after" is
 
149
  true. In this case, we want to include deleted headers in the block. */
 
150
 
 
151
  else if (after)
 
152
    {
 
153
    for (;;)
 
154
      {
 
155
      if (h->next == NULL || !header_testname(h, name, len, FALSE)) break;
 
156
      hptr = &(h->next);
 
157
      h = h->next;
 
158
      }
 
159
    }
 
160
  }
 
161
 
 
162
/* Loop for multiple header lines, taking care about continuations. At this
 
163
point, we have hptr pointing to the link field that will point to the new
 
164
header, and h containing the following header, or NULL. */
 
165
 
 
166
for (p = q = buffer; *p != 0; )
 
167
  {
 
168
  for (;;)
 
169
    {
 
170
    q = Ustrchr(q, '\n');
 
171
    if (q == NULL) q = p + Ustrlen(p);
 
172
    if (*(++q) != ' ' && *q != '\t') break;
 
173
    }
 
174
 
 
175
  new = store_get(sizeof(header_line));
 
176
  new->text = string_copyn(p, q - p);
 
177
  new->slen = q - p;
 
178
  new->type = type;
 
179
  new->next = h;
 
180
 
 
181
  *hptr = new;
 
182
  hptr = &(new->next);
 
183
 
 
184
  if (h == NULL) header_last = new;
 
185
  p = q;
 
186
  }
 
187
}
 
188
 
 
189
 
 
190
/*************************************************
 
191
*      Add new header anywhere in the chain      *
 
192
*************************************************/
 
193
 
 
194
/* This is an external interface to header_add_backend().
 
195
 
 
196
Arguments:
 
197
  after     TRUE for "after", FALSE for "before"
 
198
  name      name if adding at a specific header, else NULL
 
199
  topnot    TRUE to add at top if no header found
 
200
  type      Exim header type character (htype_something)
 
201
  format    sprintf format
 
202
  ...       format arguments
 
203
 
 
204
Returns:    nothing
 
205
*/
 
206
 
 
207
void
 
208
header_add_at_position(BOOL after, uschar *name, BOOL topnot, int type,
 
209
  char *format, ...)
 
210
{
 
211
va_list ap;
 
212
va_start(ap, format);
 
213
header_add_backend(after, name, topnot, type, format, ap);
 
214
va_end(ap);
 
215
}
 
216
 
 
217
 
 
218
 
 
219
/*************************************************
13
220
*            Add new header on end of chain      *
14
221
*************************************************/
15
222
 
16
 
/* header_last points to the last header during message reception and delivery;
17
 
otherwise it is NULL. We add new headers only when header_last is not NULL.
18
 
The function may get called sometimes when it is NULL (e.g. during address
19
 
verification where rewriting options exist).
 
223
/* This is now a convenience interface to header_add_backend().
20
224
 
21
225
Arguments:
22
226
  type      Exim header type character
29
233
void
30
234
header_add(int type, char *format, ...)
31
235
{
32
 
header_line *new;
33
236
va_list ap;
34
 
uschar buffer[HEADER_ADD_BUFFER_SIZE];
35
 
 
36
 
if (header_last == NULL) return;
37
 
 
38
237
va_start(ap, format);
39
 
if (!string_vformat(buffer, sizeof(buffer), format, ap))
40
 
  log_write(0, LOG_MAIN|LOG_PANIC_DIE, "string too long in header_add: %.100s ...",
41
 
    buffer);
 
238
header_add_backend(TRUE, NULL, FALSE, type, format, ap);
42
239
va_end(ap);
43
 
 
44
 
new = store_get(sizeof(header_line));
45
 
new->text = string_copy(buffer);
46
 
 
47
 
new->slen = Ustrlen(buffer);
48
 
new->next = NULL;
49
 
new->type = type;
50
 
 
51
 
header_last->next = new;
52
 
header_last = new;
53
 
}
 
240
}
 
241
 
 
242
 
 
243
 
 
244
/*************************************************
 
245
*        Remove (mark as old) a header           *
 
246
*************************************************/
 
247
 
 
248
/* This function is used by the filter code; it is also exported in the
 
249
local_scan() API. If no header is found, the function does nothing.
 
250
 
 
251
Arguments:
 
252
  occ           the occurrence number for multiply-defined headers
 
253
                  <= 0 means "all"; deleted headers are not counted
 
254
  name          the header name
 
255
 
 
256
Returns:        nothing
 
257
*/
 
258
 
 
259
void
 
260
header_remove(int occ, uschar *name)
 
261
{
 
262
header_line *h;
 
263
int hcount = 0;
 
264
int len = Ustrlen(name);
 
265
for (h = header_list; h != NULL; h = h->next)
 
266
  {
 
267
  if (header_testname(h, name, len, TRUE) && (occ <= 0 || ++hcount == occ))
 
268
    {
 
269
    h->type = htype_old;
 
270
    if (occ > 0) return;
 
271
    }
 
272
  }
 
273
}
 
274
 
54
275
 
55
276
 
56
277
/*************************************************
98
319
return htype_other;
99
320
}
100
321
 
 
322
 
 
323
/*************************************************
 
324
*       Scan a header for certain strings        *
 
325
*************************************************/
 
326
 
 
327
/* This function is used for the "personal" test. It scans a particular header
 
328
line for any one of a number of strings, matched caselessly either as plain
 
329
strings, or as regular expressions. If the header line contains a list of
 
330
addresses, each match is applied only to the operative part of each address in
 
331
the header, and non-regular expressions must be exact matches.
 
332
 
 
333
The patterns can be provided either as a chain of string_item structures, or
 
334
inline in the argument list, or both. If there is more than one header of the
 
335
same name, they are all searched.
 
336
 
 
337
Arguments:
 
338
  name           header name, including the trailing colon
 
339
  has_addresses  TRUE if the header contains a list of addresses
 
340
  cond           value to return if the header contains any of the strings
 
341
  strings        points to a chain of string_item blocks
 
342
  count          number of inline strings
 
343
  ...            the inline strings
 
344
 
 
345
Returns:         cond if the header exists and contains one of the strings;
 
346
                   otherwise !cond
 
347
*/
 
348
 
 
349
 
 
350
/* First we have a local subroutine to handle a single pattern */
 
351
 
 
352
static BOOL
 
353
one_pattern_match(uschar *name, int slen, BOOL has_addresses, uschar *pattern)
 
354
{
 
355
BOOL yield = FALSE;
 
356
header_line *h;
 
357
const pcre *re = NULL;
 
358
 
 
359
/* If the pattern is a regex, compile it. Bomb out if compiling fails; these
 
360
patterns are all constructed internally and should be valid. */
 
361
 
 
362
if (*pattern == '^') re = regex_must_compile(pattern, TRUE, FALSE);
 
363
 
 
364
/* Scan for the required header(s) and scan each one */
 
365
 
 
366
for (h = header_list; !yield && h != NULL; h = h->next)
 
367
  {
 
368
  if (h->type == htype_old || slen > h->slen ||
 
369
      strncmpic(name, h->text, slen) != 0)
 
370
    continue;
 
371
 
 
372
  /* If the header is a list of addresses, extract each one in turn, and scan
 
373
  it. A non-regex scan must be an exact match for the address. */
 
374
 
 
375
  if (has_addresses)
 
376
    {
 
377
    uschar *s = h->text + slen;
 
378
 
 
379
    while (!yield && *s != 0)
 
380
      {
 
381
      uschar *error, *next;
 
382
      uschar *e = parse_find_address_end(s, FALSE);
 
383
      int terminator = *e;
 
384
      int start, end, domain;
 
385
 
 
386
      /* Temporarily terminate the string at the address end while extracting
 
387
      the operative address within. */
 
388
 
 
389
      *e = 0;
 
390
      next = parse_extract_address(s, &error, &start, &end, &domain, FALSE);
 
391
      *e = terminator;
 
392
 
 
393
      /* Move on, ready for the next address */
 
394
 
 
395
      s = e;
 
396
      if (*s == ',') s++;
 
397
 
 
398
      /* If there is some kind of syntax error, just give up on this header
 
399
      line. */
 
400
 
 
401
      if (next == NULL) break;
 
402
 
 
403
      /* Otherwise, test for the pattern; a non-regex must be an exact match */
 
404
 
 
405
      yield = (re == NULL)?
 
406
        (strcmpic(next, pattern) == 0)
 
407
        :
 
408
        (pcre_exec(re, NULL, CS next, Ustrlen(next), 0, PCRE_EOPT, NULL, 0)
 
409
          >= 0);
 
410
      }
 
411
    }
 
412
 
 
413
  /* For headers that are not lists of addresses, scan the entire header line,
 
414
  and just require "contains" for non-regex patterns. */
 
415
 
 
416
  else
 
417
    {
 
418
    yield = (re == NULL)?
 
419
      (strstric(h->text, pattern, FALSE) != NULL)
 
420
      :
 
421
      (pcre_exec(re, NULL, CS h->text, h->slen, 0, PCRE_EOPT, NULL, 0) >= 0);
 
422
    }
 
423
  }
 
424
 
 
425
return yield;
 
426
}
 
427
 
 
428
 
 
429
/* The externally visible interface */
 
430
 
 
431
BOOL
 
432
header_match(uschar *name, BOOL has_addresses, BOOL cond, string_item *strings,
 
433
  int count, ...)
 
434
{
 
435
va_list ap;
 
436
string_item *s;
 
437
int i;
 
438
int slen = Ustrlen(name);
 
439
 
 
440
for (s = strings; s != NULL; s = s->next)
 
441
  {
 
442
  if (one_pattern_match(name, slen, has_addresses, s->text)) return cond;
 
443
  }
 
444
 
 
445
va_start(ap, count);
 
446
for (i = 0; i < count; i++)
 
447
  {
 
448
  if (one_pattern_match(name, slen, has_addresses, va_arg(ap, uschar *)))
 
449
    return cond;
 
450
  }
 
451
va_end(ap);
 
452
 
 
453
return !cond;
 
454
}
 
455
 
101
456
/* End of header.c */