diff -u exim-4.63/src/acl.c exim-4.63-newaclvars/src/acl.c --- exim-4.63/src/acl.c 2006-07-31 16:19:25.000000000 +0200 +++ exim-4.63-newaclvars/src/acl.c 2006-08-14 12:07:04.000000000 +0200 @@ -805,28 +805,23 @@ /* The "set" modifier is different in that its argument is "name=value" rather than just a value, and we can check the validity of the name, which - gives us a variable number to insert into the data block. */ + gives us a variable name to insert into the data block. */ if (c == ACLC_SET) { - int offset, max, n; uschar *endptr; - if (Ustrncmp(s, "acl_", 4) != 0) goto BAD_ACL_VAR; - if (s[4] == 'c') - { - offset = 0; - max = ACL_CVARS; - } - else if (s[4] == 'm') - { - offset = ACL_CVARS; - max = ACL_MVARS; - } - else goto BAD_ACL_VAR; + int old_pool = store_pool; + if (Ustrncmp(s, "acl_c", 5) == 0) + store_pool = POOL_PERM; + else if (Ustrncmp(s, "acl_m", 5) != 0) + goto BAD_ACL_VAR; + + endptr = s + 4; + while (*endptr != 0 && *endptr != '=' && !isspace(*endptr)) + ++endptr; - n = Ustrtoul(s + 5, &endptr, 10); - if ((*endptr != 0 && *endptr != '=' && !isspace(*endptr)) || n >= max) + if (endptr-s-4 < 2) { BAD_ACL_VAR: *error = string_sprintf("syntax error or unrecognized name after " @@ -834,7 +829,9 @@ return NULL; } - cond->u.varnumber = n + offset; + cond->u.varname = string_copyn(s+4, endptr-s-4); + store_pool = old_pool; + s = endptr; while (isspace(*s)) s++; } @@ -2426,11 +2423,8 @@ if (cb->type == ACLC_SET) { - int n = cb->u.varnumber; - int t = (n < ACL_CVARS)? 'c' : 'm'; - if (n >= ACL_CVARS) n -= ACL_CVARS; - debug_printf("acl_%c%d ", t, n); - lhswidth += 7; + debug_printf("acl_%s ", cb->u.varname); + lhswidth += 5 + Ustrlen(cb->u.varname); } debug_printf("= %s\n", cb->arg); @@ -2926,8 +2920,8 @@ case ACLC_SET: { int old_pool = store_pool; - if (cb->u.varnumber < ACL_CVARS) store_pool = POOL_PERM; - acl_var[cb->u.varnumber] = string_copy(arg); + if (cb->u.varname[0] == 'c') store_pool = POOL_PERM; + acl_var_create(cb->u.varname)->data.ptr = string_copy(arg); store_pool = old_pool; } break; @@ -3597,4 +3591,58 @@ return rc; } + +/************************************************* +* Helper functions for named ACL variables * +*************************************************/ + +/* Create named acl variable or reuse existing one. +ACL variables are in a binary tree (see tree.c) with +acl_var_c and acl_var_m as root nodes. + +Argument: + name pointer to the variable's name + +Returns the pointer to variable's tree_node +*/ + +tree_node * +acl_var_create(uschar *name) +{ +tree_node *node, **root; + +root = (name[0] == 'c' ? &acl_var_c : &acl_var_m); + +/* see if this name already exists */ +node = tree_search(*root, name); + +if (node == NULL) + { + node = store_get(sizeof(tree_node) + Ustrlen(name)); + Ustrcpy(node->name, name); + (void)tree_insertnode(root, node); + } + +node->data.ptr = NULL; +return node; +} + + +/* Write out a acl variable. used as callback for tree_walk. + +Arguments: + name of the variable + value of the variable + ctx FILE pointer (as a void pointer) +*/ + +void +acl_var_write(uschar *name, uschar *value, void *ctx) +{ +FILE *f = (FILE *)ctx; + +fprintf(f, "-acl%c %s %d\n%s\n", + name[0], name+1, Ustrlen(value), value); +} + /* End of acl.c */ Common subdirectories: exim-4.63/src/auths and exim-4.63-newaclvars/src/auths diff -u exim-4.63/src/expand.c exim-4.63-newaclvars/src/expand.c --- exim-4.63/src/expand.c 2006-07-31 16:19:25.000000000 +0200 +++ exim-4.63-newaclvars/src/expand.c 2006-08-14 12:50:32.000000000 +0200 @@ -1236,29 +1236,12 @@ form acl_mddd or acl_cddd, where the d's are digits, fall through to look for other names that start with acl_. */ -if (Ustrncmp(name, "acl_", 4) == 0) +if (Ustrncmp(name, "acl_c", 5) == 0 || Ustrncmp(name, "acl_m", 5) == 0) { - uschar *endptr; - int offset = -1; - int max = 0; - - if (name[4] == 'm') - { - offset = ACL_CVARS; - max = ACL_MVARS; - } - else if (name[4] == 'c') - { - offset = 0; - max = ACL_CVARS; - } - - if (offset >= 0) - { - int n = Ustrtoul(name + 5, &endptr, 10); - if (*endptr == 0 && n < max) - return (acl_var[offset + n] == NULL)? US"" : acl_var[offset + n]; - } + tree_node *node; + node = tree_search((name[4] == 'c' ? acl_var_c : acl_var_m), name + 4); + /* fail expansion for unset ACL variables if strict_acl_vars is set */ + return ((node == NULL && !strict_acl_vars) ? US"": node->data.ptr); } /* Similarly for $auth variables. */ diff -u exim-4.63/src/functions.h exim-4.63-newaclvars/src/functions.h --- exim-4.63/src/functions.h 2006-07-31 16:19:25.000000000 +0200 +++ exim-4.63-newaclvars/src/functions.h 2006-08-08 01:32:30.000000000 +0200 @@ -40,6 +40,8 @@ extern acl_block *acl_read(uschar *(*)(void), uschar **); extern int acl_check(int, uschar *, uschar *, uschar **, uschar **); +extern tree_node *acl_var_create(uschar *); +extern void acl_var_write(uschar *, uschar *, void *); extern uschar *auth_b64encode(uschar *, int); extern int auth_b64decode(uschar *, uschar **); extern int auth_call_pam(uschar *, uschar **); @@ -327,6 +329,7 @@ extern int tree_insertnode(tree_node **, tree_node *); extern tree_node *tree_search(tree_node *, uschar *); extern void tree_write(tree_node *, FILE *); +extern void tree_walk(tree_node *, void (*)(uschar*, uschar*, void*), void *); #ifdef WITH_CONTENT_SCAN extern void unspool_mbox(void); diff -u exim-4.63/src/globals.c exim-4.63-newaclvars/src/globals.c --- exim-4.63/src/globals.c 2006-07-31 16:19:25.000000000 +0200 +++ exim-4.63-newaclvars/src/globals.c 2006-08-14 11:21:26.000000000 +0200 @@ -186,7 +186,8 @@ uschar *acl_smtp_starttls = NULL; uschar *acl_smtp_vrfy = NULL; BOOL acl_temp_details = FALSE; -uschar *acl_var[ACL_CVARS + ACL_MVARS]; +tree_node *acl_var_c = NULL; +tree_node *acl_var_m = NULL; uschar *acl_verify_message = NULL; string_item *acl_warn_logged = NULL; @@ -1102,6 +1103,7 @@ BOOL srs_usehash = TRUE; BOOL srs_usetimestamp = TRUE; #endif +BOOL strict_acl_vars = FALSE; int string_datestamp_offset= -1; BOOL strip_excess_angle_brackets = FALSE; BOOL strip_trailing_dot = FALSE; diff -u exim-4.63/src/globals.h exim-4.63-newaclvars/src/globals.h --- exim-4.63/src/globals.h 2006-07-31 16:19:25.000000000 +0200 +++ exim-4.63-newaclvars/src/globals.h 2006-08-14 11:21:06.000000000 +0200 @@ -128,7 +128,8 @@ extern uschar *acl_smtp_starttls; /* ACL run for STARTTLS */ extern uschar *acl_smtp_vrfy; /* ACL run for VRFY */ extern BOOL acl_temp_details; /* TRUE to give details for 4xx error */ -extern uschar *acl_var[ACL_CVARS+ACL_MVARS]; /* User ACL variables */ +extern tree_node *acl_var_c; /* ACL connection variables */ +extern tree_node *acl_var_m; /* ACL messsage variables */ extern uschar *acl_verify_message; /* User message for verify failure */ extern string_item *acl_warn_logged; /* Logged lines */ extern uschar *acl_wherecodes[]; /* Response codes for ACL fails */ @@ -688,6 +689,7 @@ extern BOOL srs_usehash; /* SRS use hash flag */ extern BOOL srs_usetimestamp; /* SRS use timestamp flag */ #endif +extern BOOL strict_acl_vars; /* ACL variables have to be set before being used */ extern int string_datestamp_offset;/* After insertion by string_format */ extern BOOL strip_excess_angle_brackets; /* Surrounding route-addrs */ extern BOOL strip_trailing_dot; /* Remove dots at ends of domains */ Common subdirectories: exim-4.63/src/lookups and exim-4.63-newaclvars/src/lookups Common subdirectories: exim-4.63/src/pcre and exim-4.63-newaclvars/src/pcre diff -u exim-4.63/src/readconf.c exim-4.63-newaclvars/src/readconf.c --- exim-4.63/src/readconf.c 2006-07-31 16:19:25.000000000 +0200 +++ exim-4.63-newaclvars/src/readconf.c 2006-08-14 11:22:35.000000000 +0200 @@ -354,6 +354,7 @@ { "srs_usehash", opt_bool, &srs_usehash }, { "srs_usetimestamp", opt_bool, &srs_usetimestamp }, #endif + { "strict_acl_vars", opt_bool, &strict_acl_vars }, { "strip_excess_angle_brackets", opt_bool, &strip_excess_angle_brackets }, { "strip_trailing_dot", opt_bool, &strip_trailing_dot }, { "syslog_duplication", opt_bool, &syslog_duplication }, Common subdirectories: exim-4.63/src/routers and exim-4.63-newaclvars/src/routers diff -u exim-4.63/src/smtp_in.c exim-4.63-newaclvars/src/smtp_in.c --- exim-4.63/src/smtp_in.c 2006-07-31 16:19:25.000000000 +0200 +++ exim-4.63-newaclvars/src/smtp_in.c 2006-08-14 11:29:21.000000000 +0200 @@ -809,7 +809,6 @@ static void smtp_reset(void *reset_point) { -int i; store_reset(reset_point); recipients_list = NULL; rcpt_count = rcpt_defer_count = rcpt_fail_count = @@ -855,9 +854,8 @@ ratelimiters_mail = NULL; /* Updated by ratelimit ACL condition */ /* Note that ratelimiters_conn persists across resets. */ -/* The message variables follow the connection variables. */ - -for (i = 0; i < ACL_MVARS; i++) acl_var[ACL_CVARS + i] = NULL; +/* reset message ACL variables */ +acl_var_m = NULL; /* The message body variables use malloc store. They may be set if this is not the first message in an SMTP session and the previous message caused them @@ -1144,7 +1142,7 @@ smtp_start_session(void) { int size = 256; -int i, ptr; +int ptr; uschar *p, *s, *ss; /* Default values for certain variables */ @@ -1172,7 +1170,7 @@ /* Reset ACL connection variables */ -for (i = 0; i < ACL_CVARS; i++) acl_var[i] = NULL; +acl_var_c = NULL; /* Allow for trailing 0 in the command buffer. */ diff -u exim-4.63/src/spool_in.c exim-4.63-newaclvars/src/spool_in.c --- exim-4.63/src/spool_in.c 2006-07-31 16:19:25.000000000 +0200 +++ exim-4.63-newaclvars/src/spool_in.c 2006-08-14 11:30:42.000000000 +0200 @@ -236,8 +236,7 @@ one exception. DO NOT change the default value of dont_deliver, because it may be forced by an external setting. */ -for (n = 0; n < ACL_CVARS + ACL_MVARS; n++) acl_var[n] = NULL; - +acl_var_c = acl_var_m = NULL; authenticated_id = NULL; authenticated_sender = NULL; allow_unqualified_recipient = FALSE; @@ -385,41 +384,44 @@ if (Ustrncmp(big_buffer, "-acl ", 5) == 0) { int index, count; + uschar name[4]; + tree_node *node; + if (sscanf(CS big_buffer + 5, "%d %d", &index, &count) != 2) goto SPOOL_FORMAT_ERROR; - acl_var[index] = store_get(count + 1); - if (fread(acl_var[index], 1, count+1, f) < count) goto SPOOL_READ_ERROR; - acl_var[index][count] = 0; + + snprintf(CS name, 4, "%c%d", (index < 10 ? 'c' : 'm'), index); + + node = acl_var_create(name); + node->data.ptr = store_get(count + 1); + + if (fread(node->data.ptr, 1, count+1, f) < count) goto SPOOL_READ_ERROR; + ((uschar*)node->data.ptr)[count] = 0; } /* Nowadays we use "-aclc" and "-aclm" for the different types of ACL variable, because Exim may be built with different numbers of them. */ - else if (Ustrncmp(big_buffer, "-aclc ", 6) == 0) + else if (Ustrncmp(big_buffer, "-aclc ", 6) == 0 || + Ustrncmp(big_buffer, "-aclm ", 6) == 0) { - int index, count; - if (sscanf(CS big_buffer + 6, "%d %d", &index, &count) != 2) + uschar *name, *endptr; + int size = 0, ptr = 0, count; + tree_node *node; + + name = string_cat(NULL, &size, &ptr, big_buffer+4, 1); + endptr = Ustrchr(big_buffer + 6, ' '); + if (endptr == NULL) goto SPOOL_FORMAT_ERROR; + name = string_cat(name, &size, &ptr, big_buffer+6, endptr-big_buffer-6); + name[ptr] = 0; + + if (sscanf(CS endptr, " %d", &count) != 1) goto SPOOL_FORMAT_ERROR; - if (index < ACL_CVARS) - { - acl_var[index] = store_get(count + 1); - if (fread(acl_var[index], 1, count+1, f) < count) goto SPOOL_READ_ERROR; - acl_var[index][count] = 0; - } - } - - else if (Ustrncmp(big_buffer, "-aclm ", 6) == 0) - { - int index, count; - if (sscanf(CS big_buffer + 6, "%d %d", &index, &count) != 2) - goto SPOOL_FORMAT_ERROR; - if (index < ACL_MVARS) - { - index += ACL_CVARS; - acl_var[index] = store_get(count + 1); - if (fread(acl_var[index], 1, count+1, f) < count) goto SPOOL_READ_ERROR; - acl_var[index][count] = 0; - } + + node = acl_var_create(name); + node->data.ptr = store_get(count + 1); + if (fread(node->data.ptr, 1, count+1, f) < count) goto SPOOL_READ_ERROR; + ((uschar*)node->data.ptr)[count] = 0; } /* Other values */ diff -u exim-4.63/src/spool_out.c exim-4.63-newaclvars/src/spool_out.c --- exim-4.63/src/spool_out.c 2006-07-31 16:19:25.000000000 +0200 +++ exim-4.63-newaclvars/src/spool_out.c 2006-08-08 01:29:55.000000000 +0200 @@ -193,18 +193,8 @@ /* Preserve any ACL variables that are set. Because the values may contain newlines, we use an explicit length. */ -for (i = 0; i < ACL_CVARS; i++) - { - if (acl_var[i] != NULL) - fprintf(f, "-aclc %d %d\n%s\n", i, Ustrlen(acl_var[i]), acl_var[i]); - } - -for (i = 0; i < ACL_MVARS; i++) - { - int j = i + ACL_CVARS; - if (acl_var[j] != NULL) - fprintf(f, "-aclm %d %d\n%s\n", i, Ustrlen(acl_var[j]), acl_var[j]); - } +tree_walk(acl_var_c, &acl_var_write, f); +tree_walk(acl_var_m, &acl_var_write, f); /* Now any other data that needs to be remembered. */ diff -u exim-4.63/src/structs.h exim-4.63-newaclvars/src/structs.h --- exim-4.63/src/structs.h 2006-07-31 16:19:25.000000000 +0200 +++ exim-4.63-newaclvars/src/structs.h 2006-08-08 01:04:24.000000000 +0200 @@ -779,7 +779,7 @@ int type; union { BOOL negated; - int varnumber; + uschar *varname; } u; } acl_condition_block; Common subdirectories: exim-4.63/src/transports and exim-4.63-newaclvars/src/transports diff -u exim-4.63/src/tree.c exim-4.63-newaclvars/src/tree.c --- exim-4.63/src/tree.c 2006-07-31 16:19:25.000000000 +0200 +++ exim-4.63-newaclvars/src/tree.c 2006-08-14 10:57:43.000000000 +0200 @@ -341,5 +341,31 @@ return NULL; } +/************************************************* +* Walk tree recursively and execute function * +*************************************************/ + +/* +Arguments: + p root of the tree + f function to execute for each name-value-pair + ctx context data for f +*/ + +void +tree_walk(tree_node *p, void (*f)(uschar*, uschar*, void*), void *ctx) +{ +if (p == NULL) + return; + +f(p->name, p->data.ptr, ctx); + +if (p->left != NULL) + tree_walk(p->left, f, ctx); + +if (p->right != NULL) + tree_walk(p->right, f, ctx); +} + /* End of tree.c */