X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fsrc%2Frouters%2Fredirect.c;h=6bbbf37e26625593f2e619f5b5b528a366a98592;hb=163144aab02a47427340d0ecc75e2abde675f4c9;hp=005ec6f4763623b885dd3173d3b4e860b918d58e;hpb=7eb0e5d2b8453f753bd2d8e2e77cf4b7e0b24b1b;p=user%2Fhenk%2Fcode%2Fexim.git diff --git a/src/src/routers/redirect.c b/src/src/routers/redirect.c index 005ec6f47..6bbbf37e2 100644 --- a/src/src/routers/redirect.c +++ b/src/src/routers/redirect.c @@ -2,7 +2,7 @@ * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2016 */ +/* Copyright (c) University of Cambridge 1995 - 2018 */ /* See the file NOTICE for conditions of use and distribution. */ @@ -223,11 +223,11 @@ than false, there is likely to be a problem. */ if (ob->one_time) { ob->forbid_pipe = ob->forbid_file = ob->forbid_filter_reply = TRUE; - if (rblock->extra_headers != NULL || rblock->remove_headers != NULL) + if (rblock->extra_headers || rblock->remove_headers) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s router:\n " "\"headers_add\" and \"headers_remove\" are not permitted with " "\"one_time\"", rblock->name); - if (rblock->unseen || rblock->expand_unseen != NULL) + if (rblock->unseen || rblock->expand_unseen) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s router:\n " "\"unseen\" may not be used with \"one_time\"", rblock->name); } @@ -239,7 +239,7 @@ or if owngroups is set. */ if (ob->check_owner == TRUE_UNSET) ob->check_owner = rblock->check_local_user || - (ob->owners != NULL && ob->owners[0] != 0); + (ob->owners && ob->owners[0] != 0); if (ob->check_group == TRUE_UNSET) ob->check_group = (rblock->check_local_user && (ob->modemask & 020) == 0) || @@ -247,7 +247,7 @@ if (ob->check_group == TRUE_UNSET) /* If explicit qualify domain set, the preserve option is locked out */ -if (ob->qualify_domain != NULL && ob->qualify_preserve_domain) +if (ob->qualify_domain && ob->qualify_preserve_domain) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s router:\n " "only one of \"qualify_domain\" or \"qualify_preserve_domain\" must be set", rblock->name); @@ -359,7 +359,7 @@ while (generated) /* Don't do the "one_time" thing for the first pass of a 2-stage queue run. */ - if (ob->one_time && !queue_2stage) + if (ob->one_time && !f.queue_2stage) { for (parent = addr; parent->parent; parent = parent->parent) ; next->onetime_parent = parent->address; @@ -390,7 +390,7 @@ while (generated) { BOOL ignore_error = next->prop.ignore_error; next->prop = *addr_prop; - next->prop.ignore_error |= ignore_error; + next->prop.ignore_error = ignore_error || addr->prop.ignore_error; } if (errors_address) next->prop.errors_address = errors_address; @@ -465,8 +465,9 @@ while (generated) } #ifdef SUPPORT_I18N - next->prop.utf8_msg = string_is_utf8(next->address) - || (sender_address && string_is_utf8(sender_address)); + if (!next->prop.utf8_msg) + next->prop.utf8_msg = string_is_utf8(next->address) + || (sender_address && string_is_utf8(sender_address)); #endif DEBUG(D_route) @@ -562,21 +563,23 @@ addr_prop.localpart_data = deliver_localpart_data; addr_prop.errors_address = NULL; addr_prop.extra_headers = NULL; addr_prop.remove_headers = NULL; +addr_prop.variables = NULL; +tree_dup((tree_node **)&addr_prop.variables, addr->prop.variables); #ifdef EXPERIMENTAL_SRS addr_prop.srs_sender = NULL; #endif #ifdef SUPPORT_I18N -addr_prop.utf8_msg = FALSE; /*XXX should we not copy this from the parent? */ -addr_prop.utf8_downcvt = FALSE; -addr_prop.utf8_downcvt_maybe = FALSE; +addr_prop.utf8_msg = addr->prop.utf8_msg; +addr_prop.utf8_downcvt = addr->prop.utf8_downcvt; +addr_prop.utf8_downcvt_maybe = addr->prop.utf8_downcvt_maybe; #endif /* When verifying and testing addresses, the "logwrite" command in filters must be bypassed. */ -if (verify == v_none && !address_test_mode) options |= RDO_REALLOG; +if (verify == v_none && !f.address_test_mode) options |= RDO_REALLOG; /* Sort out the fixed or dynamic uid/gid. This uid is used (a) for reading the file (and interpreting a filter) and (b) for running the transports for @@ -696,10 +699,10 @@ address. Otherwise, if a local qualify_domain is provided, set that up. */ if (ob->qualify_preserve_domain) qualify_domain_recipient = addr->domain; -else if (ob->qualify_domain != NULL) +else if (ob->qualify_domain) { uschar *new_qdr = rf_expand_data(addr, ob->qualify_domain, &xrc); - if (new_qdr == NULL) return xrc; + if (!new_qdr) return xrc; qualify_domain_recipient = new_qdr; } @@ -710,16 +713,8 @@ redirect.check_owner = ob->check_owner; redirect.check_group = ob->check_group; redirect.pw = pw; -if (ob->file != NULL) - { - redirect.string = ob->file; - redirect.isfile = TRUE; - } -else - { - redirect.string = ob->data; - redirect.isfile = FALSE; - } +redirect.string = (redirect.isfile = (ob->file != NULL)) + ? ob->file : ob->data; frc = rda_interpret(&redirect, options, ob->include_directory, ob->sieve_vacation_directory, ob->sieve_enotify_mailto_owner, @@ -735,104 +730,104 @@ For FAIL and FREEZE we honour any previously set up deliveries by a filter. */ switch (frc) { case FF_NONEXIST: - addr->message = addr->user_message = NULL; - return DECLINE; + addr->message = addr->user_message = NULL; + return DECLINE; case FF_BLACKHOLE: - DEBUG(D_route) debug_printf("address :blackhole:d\n"); - generated = NULL; - discarded = US":blackhole:"; - frc = FF_DELIVERED; - break; + DEBUG(D_route) debug_printf("address :blackhole:d\n"); + generated = NULL; + discarded = US":blackhole:"; + frc = FF_DELIVERED; + break; - /* FF_DEFER and FF_FAIL can arise only as a result of explicit commands - (:defer: or :fail: in an alias file or "fail" in a filter). If a configured - message was supplied, allow it to be included in an SMTP response after - verifying. Remove any SMTP code if it is not allowed. */ + /* FF_DEFER and FF_FAIL can arise only as a result of explicit commands + (:defer: or :fail: in an alias file or "fail" in a filter). If a configured + message was supplied, allow it to be included in an SMTP response after + verifying. Remove any SMTP code if it is not allowed. */ case FF_DEFER: - yield = DEFER; - goto SORT_MESSAGE; + yield = DEFER; + goto SORT_MESSAGE; case FF_FAIL: - if ((xrc = sort_errors_and_headers(rblock, addr, verify, &addr_prop)) != OK) - return xrc; - add_generated(rblock, addr_new, addr, generated, &addr_prop, &ugid, pw); - yield = FAIL; + if ((xrc = sort_errors_and_headers(rblock, addr, verify, &addr_prop)) != OK) + return xrc; + add_generated(rblock, addr_new, addr, generated, &addr_prop, &ugid, pw); + yield = FAIL; - SORT_MESSAGE: - if (addr->message == NULL) - addr->message = (yield == FAIL)? US"forced rejection" : US"forced defer"; - else - { - int ovector[3]; - if (ob->forbid_smtp_code && - pcre_exec(regex_smtp_code, NULL, CS addr->message, - Ustrlen(addr->message), 0, PCRE_EOPT, - ovector, sizeof(ovector)/sizeof(int)) >= 0) + SORT_MESSAGE: + if (!addr->message) + addr->message = yield == FAIL ? US"forced rejection" : US"forced defer"; + else { - DEBUG(D_route) debug_printf("SMTP code at start of error message " - "is ignored because forbid_smtp_code is set\n"); - addr->message += ovector[1]; + int ovector[3]; + if (ob->forbid_smtp_code && + pcre_exec(regex_smtp_code, NULL, CS addr->message, + Ustrlen(addr->message), 0, PCRE_EOPT, + ovector, sizeof(ovector)/sizeof(int)) >= 0) + { + DEBUG(D_route) debug_printf("SMTP code at start of error message " + "is ignored because forbid_smtp_code is set\n"); + addr->message += ovector[1]; + } + addr->user_message = addr->message; + setflag(addr, af_pass_message); } - addr->user_message = addr->message; - setflag(addr, af_pass_message); - } - return yield; + return yield; - /* As in the case of a system filter, a freeze does not happen after a manual - thaw. In case deliveries were set up by the filter, we set the child count - high so that their completion does not mark the original address done. */ + /* As in the case of a system filter, a freeze does not happen after a manual + thaw. In case deliveries were set up by the filter, we set the child count + high so that their completion does not mark the original address done. */ case FF_FREEZE: - if (!deliver_manual_thaw) - { - if ((xrc = sort_errors_and_headers(rblock, addr, verify, &addr_prop)) - != OK) return xrc; - add_generated(rblock, addr_new, addr, generated, &addr_prop, &ugid, pw); - if (addr->message == NULL) addr->message = US"frozen by filter"; - addr->special_action = SPECIAL_FREEZE; - addr->child_count = 9999; - return DEFER; - } - frc = FF_NOTDELIVERED; - break; + if (!f.deliver_manual_thaw) + { + if ((xrc = sort_errors_and_headers(rblock, addr, verify, &addr_prop)) + != OK) return xrc; + add_generated(rblock, addr_new, addr, generated, &addr_prop, &ugid, pw); + if (addr->message == NULL) addr->message = US"frozen by filter"; + addr->special_action = SPECIAL_FREEZE; + addr->child_count = 9999; + return DEFER; + } + frc = FF_NOTDELIVERED; + break; - /* Handle syntax errors and :include: failures and lookup defers */ + /* Handle syntax errors and :include: failures and lookup defers */ case FF_ERROR: case FF_INCLUDEFAIL: - /* If filtertype is still FILTER_UNSET, it means that the redirection data - was never inspected, so the error was an expansion failure or failure to open - the file, or whatever. In these cases, the existing error message is probably - sufficient. */ + /* If filtertype is still FILTER_UNSET, it means that the redirection data + was never inspected, so the error was an expansion failure or failure to open + the file, or whatever. In these cases, the existing error message is probably + sufficient. */ - if (filtertype == FILTER_UNSET) return DEFER; + if (filtertype == FILTER_UNSET) return DEFER; - /* If it was a filter and skip_syntax_errors is set, we want to set up - the error message so that it can be logged and mailed to somebody. */ + /* If it was a filter and skip_syntax_errors is set, we want to set up + the error message so that it can be logged and mailed to somebody. */ - if (filtertype != FILTER_FORWARD && ob->skip_syntax_errors) - { - eblock = store_get(sizeof(error_block)); - eblock->next = NULL; - eblock->text1 = addr->message; - eblock->text2 = NULL; - addr->message = addr->user_message = NULL; - } + if (filtertype != FILTER_FORWARD && ob->skip_syntax_errors) + { + eblock = store_get(sizeof(error_block), FALSE); + eblock->next = NULL; + eblock->text1 = addr->message; + eblock->text2 = NULL; + addr->message = addr->user_message = NULL; + } - /* Otherwise set up the error for the address and defer. */ + /* Otherwise set up the error for the address and defer. */ - else - { - addr->basic_errno = ERRNO_BADREDIRECT; - addr->message = string_sprintf("error in %s %s: %s", - (filtertype != FILTER_FORWARD)? "filter" : "redirect", - (ob->data == NULL)? "file" : "data", - addr->message); - return DEFER; - } + else + { + addr->basic_errno = ERRNO_BADREDIRECT; + addr->message = string_sprintf("error in %s %s: %s", + filtertype == FILTER_FORWARD ? "redirect" : "filter", + ob->data ? "data" : "file", + addr->message); + return DEFER; + } } @@ -854,7 +849,7 @@ if (eblock != NULL) if (!moan_skipped_syntax_errors( rblock->name, /* For message content */ eblock, /* Ditto */ - (verify != v_none || address_test_mode)? + (verify != v_none || f.address_test_mode)? NULL : ob->syntax_errors_to, /* Who to mail */ generated != NULL, /* True if not all failed */ ob->syntax_errors_text)) /* Custom message */ @@ -886,7 +881,7 @@ generated anything. Log what happened to this address, and return DISCARD. */ if (frc == FF_DELIVERED) { - if (generated == NULL && verify == v_none && !address_test_mode) + if (generated == NULL && verify == v_none && !f.address_test_mode) { log_write(0, LOG_MAIN, "=> %s <%s> R=%s", discarded, addr->address, rblock->name);