Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Postfix/src/bounce/   (Postfix Mailserver Version 3.11©)  Datei vom 2.9.2021 mit Größe 16 kB image not shown  

Quelle  bounce_template.c

  Sprache: C
 

/*++
/* NAME
/* bounce_template 3
/* SUMMARY
/* bounce template support
/* SYNOPSIS
/* #include <bounce_template.h>
/*
/* BOUNCE_TEMPLATE *bounce_template_create(def_template)
/* const BOUNCE_TEMPLATE *def_template;
/*
/* void bounce_template_free(template)
/* BOUNCE_TEMPLATE *template;
/*
/* void bounce_template_load(template, stream, buffer, origin)
/* BOUNCE_TEMPLATE *template;
/* VSTREAM *stream;
/* const char *buffer;
/* const char *origin;
/*
/* void bounce_template_headers(out_fn, stream, template,
/* rcpt, postmaster_copy)
/* int (*out_fn)(VSTREAM *, const char *, ...);
/* VSTREAM *stream;
/* BOUNCE_TEMPLATE *template;
/* const char *rcpt;
/* int postmaster_copy;
/*
/* const char *bounce_template_encoding(template)
/* BOUNCE_TEMPLATE *template;
/*
/* const char *bounce_template_charset(template)
/* BOUNCE_TEMPLATE *template;
/*
/* void bounce_template_expand(out_fn, stream, template)
/* int (*out_fn)(VSTREAM *, const char *);
/* VSTREAM *stream;
/* BOUNCE_TEMPLATE *template;
/*
/* void bounce_template_dump(stream, template)
/* VSTREAM *stream;
/* BOUNCE_TEMPLATE *template;
/*
/* int IS_FAILURE_TEMPLATE(template)
/* int IS_DELAY_TEMPLATE(template)
/* int IS_SUCCESS_TEMPLATE(template)
/* BOUNCE_TEMPLATE *template;
/* DESCRIPTION
/* This module implements the built-in and external bounce
/* message template support. The content of a template are
/* private. To access information within a template, use
/* the API described in this document.
/*
/* bounce_template_create() creates a template, with the
/* specified default settings. The template defaults are not
/* copied.
/*
/* bounce_template_free() destroys a bounce message template.
/*
/* bounce_template_load() overrides a bounce template with the
/* specified buffer from the specified origin. The buffer and
/* origin are copied. Specify a null buffer and origin pointer
/* to reset the template to the defaults specified with
/* bounce_template_create().
/*
/* bounce_template_headers() sends the postmaster or non-postmaster
/* From/Subject/To message headers to the specified stream.
/* The recipient address is expected to be in RFC822 external
/* form. The postmaster_copy argument is one of POSTMASTER_COPY
/* or NO_POSTMASTER_COPY.
/*
/* bounce_template_encoding() returns the encoding (MAIL_ATTR_ENC_7BIT
/* or MAIL_ATTR_ENC_8BIT) for the bounce template message text.
/*
/* bounce_template_charset() returns the character set for the
/* bounce template message text.
/*
/* bounce_template_expand() expands the body text of the
/* specified template and writes the result to the specified
/* stream.
/*
/* bounce_template_dump() dumps the specified template to the
/* specified stream.
/*
/* The IS_MUMBLE_TEMPLATE() macros are predicates that
/* determine whether the template is of the specified type.
/* DIAGNOSTICS
/* Fatal error: out of memory, undefined macro name in template.
/* SEE ALSO
/* bounce_templates(3) bounce template group support
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/


/* System library. */

#include <sys_defs.h>
#include <string.h>
#include <ctype.h>

#ifdef STRCASECMP_IN_STRINGS_H
#include <strings.h>
#endif

/* Utility library. */

#include <msg.h>
#include <mac_expand.h>
#include <split_at.h>
#include <stringops.h>
#include <mymalloc.h>
#ifndef NO_EAI
#include <midna_domain.h>
#endif

/* Global library. */

#include <mail_params.h>
#include <mail_proto.h>
#include <mail_conf.h>
#include <is_header.h>
#include <hfrom_format.h>

/* Application-specific. */

#include <bounce_template.h>
#include <bounce_service.h>

 /*
  * The following tables implement support for bounce template expansions of
  * $<parameter_name>_days ($<parameter_name>_hours, etc.). The expansion of
  * these is the actual parameter value divided by the number of seconds in a
  * day (hour, etc.), so that we can produce nicely formatted bounce messages
  * with time values converted into the appropriate units.
  * 
  * Ideally, the bounce template processor would strip the _days etc. suffix
  * from the parameter name, and use the parameter name to look up the actual
  * parameter value and its default value (the default value specifies the
  * default time unit of that parameter (seconds, minutes, etc.)), and use
  * this to convert the parameter string value into the corresponding number
  * of seconds. The bounce template processor would then use the _hours etc.
  * suffix from the bounce template to divide this number by the number of
  * seconds in an hour, etc. and produce the number that is needed for the
  * template.
  * 
  * Unfortunately, there exists no code to look up default values by parameter
  * name. If such code existed, then we could do the _days, _hours, etc.
  * conversion with every main.cf time parameter without having to know in
  * advance what time parameter names exist.
  * 
  * So we have to either maintain our own table of all time related main.cf
  * parameter names and defaults (like the postconf command does) or we make
  * a special case for a few parameters of special interest.
  * 
  * We go for the second solution. There are only a few parameters that need
  * this treatment, and there will be more special cases when individual
  * queue files get support for individual expiration times, and when other
  * queue file information needs to be reported in bounce template messages.
  * 
  * A really lame implementation would simply strip the optional s, h, d, etc.
  * suffix from the actual (string) parameter value and not do any conversion
  * at all to hours, days or weeks. But then the information in delay warning
  * notices could be seriously incorrect.
  */

typedef struct {
    const char *suffix;   /* days, hours, etc. */
    int     suffix_len;   /* byte count */
    int     divisor;   /* divisor */
} BOUNCE_TIME_DIVISOR;

#define STRING_AND_LEN(x) (x), (sizeof(x) - 1)

static const BOUNCE_TIME_DIVISOR time_divisors[] = {
    STRING_AND_LEN("seconds"), 1,
    STRING_AND_LEN("minutes"), 60,
    STRING_AND_LEN("hours"), 60 * 60,
    STRING_AND_LEN("days"), 24 * 60 * 60,
    STRING_AND_LEN("weeks"), 7 * 24 * 60 * 60,
    00,
};

 /*
  * The few special-case main.cf parameters that have support for _days, etc.
  * suffixes for automatic conversion when expanded into a bounce template.
  */

typedef struct {
    const char *param_name;  /* parameter name */
    int     param_name_len;  /* name length */
    int    *value;   /* parameter value */
} BOUNCE_TIME_PARAMETER;

static const BOUNCE_TIME_PARAMETER time_parameter[] = {
    STRING_AND_LEN(VAR_DELAY_WARN_TIME), &var_delay_warn_time,
    STRING_AND_LEN(VAR_MAX_QUEUE_TIME), &var_max_queue_time,
    00,
};

 /*
  * Parameters whose value may have to be converted to UTF-8 for presentation
  * purposes.
  */

typedef struct {
    const char *param_name;  /* parameter name */
    char  **value;   /* parameter value */
} BOUNCE_STR_PARAMETER;

static const BOUNCE_STR_PARAMETER str_parameter[] = {
    VAR_MYHOSTNAME, &var_myhostname,
    VAR_MYDOMAIN, &var_mydomain,
    00,
};

 /*
  * SLMs.
  */

#define STR(x) vstring_str(x)

/* bounce_template_create - create one template */

BOUNCE_TEMPLATE *bounce_template_create(const BOUNCE_TEMPLATE *prototype)
{
    BOUNCE_TEMPLATE *tp;

    tp = (BOUNCE_TEMPLATE *) mymalloc(sizeof(*tp));
    *tp = *prototype;
    return (tp);
}

/* bounce_template_free - destroy one template */

void    bounce_template_free(BOUNCE_TEMPLATE *tp)
{
    if (tp->buffer) {
 myfree(tp->buffer);
 myfree((void *) tp->origin);
    }
    myfree((void *) tp);
}

/* bounce_template_reset - reset template to default */

static void bounce_template_reset(BOUNCE_TEMPLATE *tp)
{
    myfree(tp->buffer);
    myfree((void *) tp->origin);
    *tp = *(tp->prototype);
}

/* bounce_template_load - override one template */

void    bounce_template_load(BOUNCE_TEMPLATE *tp, const char *origin,
                const char *buffer)
{

    /*
     * Clean up after a previous call.
     */

    if (tp->buffer)
 bounce_template_reset(tp);

    /*
     * Postpone the work of template parsing until it is really needed. Most
     * bounce service calls never need a template.
     */

    if (buffer && origin) {
 tp->flags |= BOUNCE_TMPL_FLAG_NEW_BUFFER;
 tp->buffer = mystrdup(buffer);
 tp->origin = mystrdup(origin);
    }
}

/* bounce_template_parse_buffer - initialize template */

static void bounce_template_parse_buffer(BOUNCE_TEMPLATE *tp)
{
    char   *tval = tp->buffer;
    char   *cp;
    char  **cpp;
    int     cpp_len;
    int     cpp_used;
    int     hlen;
    char   *hval;

    /*
     * Sanity check.
     */

    if ((tp->flags & BOUNCE_TMPL_FLAG_NEW_BUFFER) == 0)
 msg_panic("bounce_template_parse_buffer: nothing to do here");
    tp->flags &= ~BOUNCE_TMPL_FLAG_NEW_BUFFER;

    /*
     * Discard the unusable template and use the default one instead.
     */

#define CLEANUP_AND_RETURN() do { \
 bounce_template_reset(tp); \
 return; \
    } while (0)

    /*
     * Parse pseudo-header labels and values.
     * 
     * XXX EAI: allow UTF8 in template headers when responding to SMTPUTF8
     * message. Sending SMTPUTF8 in response to non-SMTPUTF8 mail would make
     * no sense.
     */

#define GETLINE(line, buf) \
        (((line) = (buf)) != 0 ? ((buf) = split_at((buf), '\n'), (line)) : 0)

    while ((GETLINE(cp, tval)) != 0 && (hlen = is_header(cp)) > 0) {
 for (hval = cp + hlen; *hval && (*hval == ':' || ISSPACE(*hval)); hval++)
     *hval = 0;
 if (*hval == 0) {
     msg_warn("%s: empty \"%s\" header value in %s template "
       "-- ignoring this template",
       tp->origin, cp, tp->class);
     CLEANUP_AND_RETURN();
 }
 if (!allascii(hval)) {
     msg_warn("%s: non-ASCII \"%s\" header value in %s template "
       "-- ignoring this template",
       tp->origin, cp, tp->class);
     CLEANUP_AND_RETURN();
 }
 if (strcasecmp("charset", cp) == 0) {
     tp->mime_charset = hval;
 } else if (strcasecmp("from", cp) == 0) {
     tp->std_from = tp->obs_from = hval;
 } else if (strcasecmp("subject", cp) == 0) {
     tp->subject = hval;
 } else if (strcasecmp("postmaster-subject", cp) == 0) {
     if (tp->postmaster_subject == 0) {
  msg_warn("%s: inapplicable \"%s\" header label in %s template "
    "-- ignoring this template",
    tp->origin, cp, tp->class);
  CLEANUP_AND_RETURN();
     }
     tp->postmaster_subject = hval;
 } else {
     msg_warn("%s: unknown \"%s\" header label in %s template "
       "-- ignoring this template",
       tp->origin, cp, tp->class);
     CLEANUP_AND_RETURN();
 }
    }

    /*
     * Skip blank lines between header and message text.
     */

    while (cp && (*cp == 0 || allspace(cp)))
 (void) GETLINE(cp, tval);
    if (cp == 0) {
 msg_warn("%s: missing message text in %s template "
   "-- ignoring this template",
   tp->origin, tp->class);
 CLEANUP_AND_RETURN();
    }

    /*
     * Is this 7bit or 8bit text? If the character set is US-ASCII, then
     * don't allow 8bit text. Don't assume 8bit when charset was changed.
     */

#define NON_ASCII(p) ((p) && *(p) && !allascii((p)))

    if (NON_ASCII(cp) || NON_ASCII(tval)) {
 if (strcasecmp(tp->mime_charset, "us-ascii") == 0) {
     msg_warn("%s: 8-bit message text in %s template",
       tp->origin, tp->class);
     msg_warn("please specify a charset value other than us-ascii");
     msg_warn("-- ignoring this template for now");
     CLEANUP_AND_RETURN();
 }
 tp->mime_encoding = MAIL_ATTR_ENC_8BIT;
    }

    /*
     * Collect the message text and null-terminate the result.
     */

    cpp_len = 10;
    cpp_used = 0;
    cpp = (char **) mymalloc(sizeof(*cpp) * cpp_len);
    while (cp) {
 cpp[cpp_used++] = cp;
 if (cpp_used >= cpp_len) {
     cpp = (char **) myrealloc((void *) cpp,
          sizeof(*cpp) * 2 * cpp_len);
     cpp_len *= 2;
 }
 (void) GETLINE(cp, tval);
    }
    cpp[cpp_used] = 0;
    tp->message_text = (const char **) cpp;
}

/* bounce_template_lookup - lookup $name value */

static const char *bounce_template_lookup(const char *key, int unused_mode,
               void *context)
{
    BOUNCE_TEMPLATE *tp = (BOUNCE_TEMPLATE *) context;
    const BOUNCE_TIME_PARAMETER *bp;
    const BOUNCE_TIME_DIVISOR *bd;
    const BOUNCE_STR_PARAMETER *sp;
    static VSTRING *buf;
    int     result;
    const char *asc_val;
    const char *utf8_val;

    /*
     * Look for parameter names that can have a time unit suffix, and scale
     * the time value according to the suffix.
     */

    for (bp = time_parameter; bp->param_name; bp++) {
 if (strncmp(key, bp->param_name, bp->param_name_len) == 0
     && key[bp->param_name_len] == '_') {
     for (bd = time_divisors; bd->suffix; bd++) {
  if (strcmp(key + bp->param_name_len + 1, bd->suffix) == 0) {
      result = bp->value[0] / bd->divisor;
      if (result > 999 && bd->divisor < 86400) {
   msg_warn("%s: excessive result \"%d\" in %s "
     "template conversion of parameter \"%s\"",
     tp->origin, result, tp->class, key);
   msg_warn("please increase time unit \"%s\" of \"%s\" "
         "in %s template", bd->suffix, key, tp->class);
   msg_warn("for instructions see the bounce(5) manual");
      } else if (result == 0 && bp->value[0] && bd->divisor > 1) {
   msg_warn("%s: zero result in %s template "
     "conversion of parameter \"%s\"",
     tp->origin, tp->class, key);
   msg_warn("please reduce time unit \"%s\" of \"%s\" "
         "in %s template", bd->suffix, key, tp->class);
   msg_warn("for instructions see the bounce(5) manual");
      }
      if (buf == 0)
   buf = vstring_alloc(10);
      vstring_sprintf(buf, "%d", result);
      return (STR(buf));
  }
     }
     msg_fatal("%s: unrecognized suffix \"%s\" in parameter \"%s\"",
        tp->origin,
        key + bp->param_name_len + 1, key);
 }
    }

    /*
     * Look for parameter names that may have to be up-converted for
     * presentation purposes.
     */

#ifndef NO_EAI
    if (var_smtputf8_enable) {
 for (sp = str_parameter; sp->param_name; sp++) {
     if (strcmp(key, sp->param_name) == 0) {
  asc_val = sp->value[0];
  if (!allascii(asc_val)) {
      msg_warn("%s: conversion \"%s\" failed: "
        "non-ASCII input value: \"%s\"",
        tp->origin, key, asc_val);
      return (asc_val);
  } else if ((utf8_val = midna_domain_to_utf8(asc_val)) == 0) {
      msg_warn("%s: conversion \"%s\" failed: "
        "input value: \"%s\"",
        tp->origin, key, asc_val);
      return (asc_val);
  } else {
      return (utf8_val);
  }
     }
 }
    }
#endif
    return (mail_conf_lookup_eval(key));
}

/* bounce_template_headers - send template headers */

void    bounce_template_headers(BOUNCE_XP_PRN_FN out_fn, VSTREAM *fp,
            BOUNCE_TEMPLATE *tp,
            const char *rcpt,
            int postmaster_copy)
{
    if (tp->flags & BOUNCE_TMPL_FLAG_NEW_BUFFER)
 bounce_template_parse_buffer(tp);

    out_fn(fp, "From: %s", bounce_hfrom_format == HFROM_FORMAT_CODE_STD ?
    tp->std_from : tp->obs_from);
    out_fn(fp, "Subject: %s", tp->postmaster_subject && postmaster_copy ?
    tp->postmaster_subject : tp->subject);
    out_fn(fp, "To: %s", rcpt);
}

/* bounce_template_expand - expand template to stream */

void    bounce_template_expand(BOUNCE_XP_PUT_FN out_fn, VSTREAM *fp,
                  BOUNCE_TEMPLATE *tp)
{
    VSTRING *buf = vstring_alloc(100);
    const char **cpp;
    int     stat;

    if (tp->flags & BOUNCE_TMPL_FLAG_NEW_BUFFER)
 bounce_template_parse_buffer(tp);

    for (cpp = tp->message_text; *cpp; cpp++) {
 stat = mac_expand(buf, *cpp, MAC_EXP_FLAG_PRINTABLE, (char *) 0,
     bounce_template_lookup, (void *) tp);
 if (stat & MAC_PARSE_ERROR)
     msg_fatal("%s: bad $name syntax in %s template: %s",
        tp->origin, tp->class, *cpp);
 if (stat & MAC_PARSE_UNDEF)
     msg_fatal("%s: undefined $name in %s template: %s",
        tp->origin, tp->class, *cpp);
 out_fn(fp, STR(buf));
    }
    vstring_free(buf);
}

/* bounce_template_dump - dump template to stream */

void    bounce_template_dump(VSTREAM *fp, BOUNCE_TEMPLATE *tp)
{
    const char **cpp;

    if (tp->flags & BOUNCE_TMPL_FLAG_NEW_BUFFER)
 bounce_template_parse_buffer(tp);

    vstream_fprintf(fp, "Charset: %s\n", tp->mime_charset);
    vstream_fprintf(fp, "From: %s\n", bounce_hfrom_format == HFROM_FORMAT_CODE_STD ?
      tp->std_from : tp->obs_from);
    vstream_fprintf(fp, "Subject: %s\n", tp->subject);
    if (tp->postmaster_subject)
 vstream_fprintf(fp, "Postmaster-Subject: %s\n",
   tp->postmaster_subject);
    vstream_fprintf(fp, "\n");
    for (cpp = tp->message_text; *cpp; cpp++)
 vstream_fprintf(fp, "%s\n", *cpp);
}

Messung V0.5 in Prozent
C=76 H=94 G=85

¤ Dauer der Verarbeitung: 0.24 Sekunden  (vorverarbeitet am  2026-08-08) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.