diff --git a/configure.in b/configure.in index 4c6cf3bd5110075e67a7eb35f40701f67d1e8743..3934fdda4dcd2b071accc0b80020e11887701e8a 100644 --- a/configure.in +++ b/configure.in @@ -60,6 +60,7 @@ src/Makefile src/lib-sieve/Makefile src/lib-sieve/plugins/Makefile src/lib-sieve/plugins/vacation/Makefile +src/lib-sieve/plugins/subaddress/Makefile src/sieve-bin/Makefile stamp.h]) diff --git a/src/lib-sieve/ext-envelope.c b/src/lib-sieve/ext-envelope.c index 70698ceac607ca9bb5ac97ac385536294d39215b..1eb7362f1071a9063af96625f6f2421388314cf0 100644 --- a/src/lib-sieve/ext-envelope.c +++ b/src/lib-sieve/ext-envelope.c @@ -154,7 +154,7 @@ static bool ext_envelope_opcode_dump case OPT_MATCH_TYPE: break; case OPT_ADDRESS_PART: - sieve_opr_address_part_dump(sbin, address); + sieve_opr_address_part_dump(interp, sbin, address); break; default: return FALSE; diff --git a/src/lib-sieve/plugins/Makefile.am b/src/lib-sieve/plugins/Makefile.am index d1b05da32d95aed34fee41fc27d955fef9a493b5..f4041635a06669c46ae3fdb4e7a364e103782a41 100644 --- a/src/lib-sieve/plugins/Makefile.am +++ b/src/lib-sieve/plugins/Makefile.am @@ -1 +1 @@ -SUBDIRS = vacation +SUBDIRS = vacation subaddress diff --git a/src/lib-sieve/plugins/subaddress/Makefile.am b/src/lib-sieve/plugins/subaddress/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..befb510b6c3e23664b0ed71519155ff248760fad --- /dev/null +++ b/src/lib-sieve/plugins/subaddress/Makefile.am @@ -0,0 +1,12 @@ +noinst_LIBRARIES = lib_ext_subaddress.a + +AM_CPPFLAGS = \ + -I../../ \ + -I$(dovecot_incdir) \ + -I$(dovecot_incdir)/src/lib \ + -I$(dovecot_incdir)/src/lib-mail \ + -I$(dovecot_incdir)/src/lib-storage + +lib_ext_subaddress_a_SOURCES = \ + ext-subaddress.c + diff --git a/src/lib-sieve/plugins/subaddress/ext-subaddress.c b/src/lib-sieve/plugins/subaddress/ext-subaddress.c new file mode 100644 index 0000000000000000000000000000000000000000..25f881471f3b39328786bb29b31c82c327d13e8e --- /dev/null +++ b/src/lib-sieve/plugins/subaddress/ext-subaddress.c @@ -0,0 +1,121 @@ +#include <stdio.h> + +#include "sieve-common.h" + +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-address-parts.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" + +/* Forward declarations */ +static bool ext_subaddress_load(int ext_id); +static bool ext_subaddress_validator_load(struct sieve_validator *validator); +static bool ext_subaddress_interpreter_load + (struct sieve_interpreter *interpreter); + +/* Extension definitions */ + +int ext_my_id; + +const struct sieve_extension subaddress_extension = { + "subaddress", + ext_subaddress_load, + ext_subaddress_validator_load, + NULL, + ext_subaddress_interpreter_load, + NULL, + NULL +}; + +static bool ext_subaddress_load(int ext_id) +{ + ext_my_id = ext_id; + + return TRUE; +} + +/* */ + +static const char *subaddress_user_extract_from + (const struct message_address *address) +{ + i_info("subaddress: user: %s.", address->mailbox); + return address->mailbox; +} + +static const char *subaddress_detail_extract_from + (const struct message_address *address) +{ + i_info("subaddress: detail: %s.", address->mailbox); + return address->mailbox; +} + +enum ext_subaddress_address_part { + SUBADDRESS_USER, + SUBADDRESS_DETAIL +}; + +const struct sieve_address_part user_address_part = { + "user", + SIEVE_ADDRESS_PART_CUSTOM, + &subaddress_extension, + SUBADDRESS_USER, + subaddress_user_extract_from +}; + +const struct sieve_address_part detail_address_part = { + "detail", + SIEVE_ADDRESS_PART_CUSTOM, + &subaddress_extension, + SUBADDRESS_DETAIL, + subaddress_detail_extract_from +}; + +static const struct sieve_address_part *ext_subaddress_get_part + (unsigned int code) +{ + switch ( code ) { + case SUBADDRESS_USER: + return &user_address_part; + case SUBADDRESS_DETAIL: + return &detail_address_part; + default: + break; + } + + return NULL; +} + +const struct sieve_address_part_extension subaddress_addrp_extension = { + NULL, + + ext_subaddress_get_part +}; + +/* Load extension into validator */ + +static bool ext_subaddress_validator_load(struct sieve_validator *validator) +{ + sieve_address_part_register + (validator, &user_address_part, ext_my_id); + sieve_address_part_register + (validator, &detail_address_part, ext_my_id); + + return TRUE; +} + +/* Load extension into interpreter */ + +static bool ext_subaddress_interpreter_load + (struct sieve_interpreter *interpreter) +{ + sieve_address_part_extension_set + (interpreter, ext_my_id, &subaddress_addrp_extension); + + return TRUE; +} + + diff --git a/src/lib-sieve/plugins/subaddress/rfc3598.txt b/src/lib-sieve/plugins/subaddress/rfc3598.txt new file mode 100644 index 0000000000000000000000000000000000000000..3bbc5976f7c26c113fca072f30ee907152e92fb1 --- /dev/null +++ b/src/lib-sieve/plugins/subaddress/rfc3598.txt @@ -0,0 +1,339 @@ + + + + + + +Network Working Group K. Murchison +Request for Comments: 3598 Oceana Matrix Ltd. +Category: Standards Track September 2003 + + + Sieve Email Filtering -- Subaddress Extension + +Status of this Memo + + This document specifies an Internet standards track protocol for the + Internet community, and requests discussion and suggestions for + improvements. Please refer to the current edition of the "Internet + Official Protocol Standards" (STD 1) for the standardization state + and status of this protocol. Distribution of this memo is unlimited. + +Copyright Notice + + Copyright (C) The Internet Society (2003). All Rights Reserved. + +Abstract + + On email systems that allow for "subaddressing" or "detailed + addressing" (e.g., "ken+sieve@example.org"), it is sometimes + desirable to make comparisons against these sub-parts of addresses. + This document defines an extension to the Sieve mail filtering + language that allows users to compare against the user and detail + parts of an address. + +Table of Contents + + 1. Introduction. . . . . . . . . . . . . . . . . . . . . . . . . 2 + 2. Capability Identifier . . . . . . . . . . . . . . . . . . . . 2 + 3. Subaddress Comparisons. . . . . . . . . . . . . . . . . . . . 2 + 4. Security Considerations . . . . . . . . . . . . . . . . . . . 4 + 5. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 4 + 6. Normative References. . . . . . . . . . . . . . . . . . . . . 4 + 7. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 5 + 8. Intellectual Property Statement . . . . . . . . . . . . . . . 5 + 9. Author's Address. . . . . . . . . . . . . . . . . . . . . . . 5 + 10. Full Copyright Statement. . . . . . . . . . . . . . . . . . . 6 + + + + + + + + + + + +Murchison Standards Track [Page 1] + +RFC 3598 Sieve Email Filtering September 2003 + + +1. Introduction + + Subaddressing is the practice of appending some "detail" information + to the local-part of an [IMAIL] address to indicate that the message + should be delivered to the mailbox specified by the "detail" + information. The "detail" information is prefixed with a special + "separator character" (typically "+") which forms the boundary + between the "user" (original local-part) and the "detail" sub-parts + of the address, much like the "@" character forms the boundary + between the local-part and domain. + + Typical uses of subaddressing might be: + + - A message addressed to "ken+sieve@example.org" is delivered into a + mailbox called "sieve" belonging to the user "ken". + + - A message addressed to "5551212#123@example.org" is delivered to + the voice mailbox number "123" at phone number "5551212". + + This document describes an extension to the Sieve language defined by + [SIEVE] for comparing against the "user" and "detail" sub-parts of an + address. + + Conventions for notations are as in [SIEVE] section 1.1, including + use of [KEYWORDS]. + +2. Capability Identifier + + The capability string associated with the extension defined in this + document is "subaddress". + +3. Subaddress Comparisons + + Commands that act exclusively on addresses may take the optional + tagged arguments ":user" and ":detail" to specify what sub-part of + the local-part of the address will be acted upon. + + NOTE: In most cases, the envelope "to" address is the preferred + address to examine for subaddress information when the desire is to + sort messages based on how they were addressed so as to get to a + specific recipient. The envelope address is, after all, the reason a + given message is being processed by a given sieve script for a given + user. This is particularly true when mailing lists, aliases, and + "virtual domains" are involved since the envelope may be the only + source of detail information for the specific recipient. + + + + + + +Murchison Standards Track [Page 2] + +RFC 3598 Sieve Email Filtering September 2003 + + + The ":user" argument specifies that sub-part of the local-part which + lies to the left of the separator character (e.g., "ken" in + "ken+sieve@example.org"). If no separator character exists, then + ":user" specifies the entire left-side of the address (equivalent to + ":localpart"). + + The ":detail" argument specifies that sub-part of the local-part + which lies to the right of the separator character (e.g., "sieve" in + "ken+sieve@example.org"). If no separator character exists, the test + evaluates to false. If nothing lies to the right of the separator + character, then ":detail" ":is" the null key (""). Otherwise, the + ":detail" sub-part contains the null key. + + Implementations MUST make sure that the separator character matches + that which is used and/or allowed by the encompassing mail system, + otherwise unexpected results might occur. Implementations SHOULD + allow the separator character to be configurable so that they may be + used with a variety of mail systems. Note that the mechanisms used + to define and/or query the separator character used by the mail + system are outside the scope of this document. + + The ":user" and ":detail" address parts are subject to the same rules + and restrictions as the standard address parts defined in [SIEVE]. + For convenience, the "ADDRESS-PART" syntax element defined in [SIEVE] + is augmented here as follows: + + ADDRESS-PART =/ ":user" / ":detail" + + A diagram showing the ADDRESS-PARTs of a email address utilizing a + separator character of '+' is shown below: + + :user "+" :detail "@" :domain + `-----------------' + :local-part + + Example: + + require "subaddress"; + + # File mailing list messages (subscribed as "ken+mta-filters"). + if envelope :detail "to" "mta-filters" { + fileinto "inbox.ietf-mta-filters"; + } + + # If a message is not to me (ignoring +detail), junk it. + if not allof (address :user ["to", "cc", "bcc"] "ken", + address :domain ["to", "cc", "bcc"] "example.org") { + discard; + + + +Murchison Standards Track [Page 3] + +RFC 3598 Sieve Email Filtering September 2003 + + + } + + # Redirect all mail sent to +foo. + if envelope :detail ["to", "cc", "bcc"] "foo" { + redirect "ken@example.edu"; + } + +4. Security Considerations + + Security considerations are discussed in [SIEVE]. It is believed + that this extension does not introduce any additional security + concerns. + +5. IANA Considerations + + The following template specifies the IANA registration of the Sieve + extension specified in this document: + + To: iana@iana.org + Subject: Registration of new Sieve extension + + Capability name: subaddress + Capability keyword: subaddress + Capability arguments: N/A + Standards Track/RFC 3598 + Person and email address to contact for further information: + + Kenneth Murchison + ken@oceana.com + + This information has been added to the list of sieve extensions given + on http://www.iana.org/assignments/sieve-extensions. + +6. Normative References + + [IMAIL] Resnick, P., Ed., "Internet Message Format", RFC 2822, + April 2001. + + [KEYWORDS] Bradner, S., "Key words for use in RFCs to Indicate + Requirement Levels", BCP 14, RFC 2119, March 1997. + + [SIEVE] Showalter, T., "Sieve: A Mail Filtering Language", RFC + 3028, January 2001. + + + + + + + + +Murchison Standards Track [Page 4] + +RFC 3598 Sieve Email Filtering September 2003 + + +7. Acknowledgments + + Thanks to Tim Showalter, Alexey Melnikov, Michael Salmon, Randall + Gellens, Philip Guenther and Jutta Degener for their help with this + document. + +8. Intellectual Property Statement + + The IETF takes no position regarding the validity or scope of any + intellectual property or other rights that might be claimed to + pertain to the implementation or use of the technology described in + this document or the extent to which any license under such rights + might or might not be available; neither does it represent that it + has made any effort to identify any such rights. Information on the + IETF's procedures with respect to rights in standards-track and + standards-related documentation can be found in BCP-11. Copies of + claims of rights made available for publication and any assurances of + licenses to be made available, or the result of an attempt made to + obtain a general license or permission for the use of such + proprietary rights by implementors or users of this specification can + be obtained from the IETF Secretariat. + + The IETF invites any interested party to bring to its attention any + copyrights, patents or patent applications, or other proprietary + rights which may cover technology that may be required to practice + this standard. Please address the information to the IETF Executive + Director. + +9. Author's Address + + Kenneth Murchison + Oceana Matrix Ltd. + 21 Princeton Place + Orchard Park, NY 14127 + + EMail: ken@oceana.com + + + + + + + + + + + + + + + +Murchison Standards Track [Page 5] + +RFC 3598 Sieve Email Filtering September 2003 + + +10. Full Copyright Statement + + Copyright (C) The Internet Society (2003). All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that the above copyright notice and this paragraph are + included on all such copies and derivative works. However, this + document itself may not be modified in any way, such as by removing + the copyright notice or references to the Internet Society or other + Internet organizations, except as needed for the purpose of + developing Internet standards in which case the procedures for + copyrights defined in the Internet Standards process must be + followed, or as required to translate it into languages other than + English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assignees. + + This document and the information contained herein is provided on an + "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +Acknowledgement + + Funding for the RFC Editor function is currently provided by the + Internet Society. + + + + + + + + + + + + + + + + + + + +Murchison Standards Track [Page 6] + diff --git a/src/lib-sieve/plugins/subaddress/subaddress.sieve b/src/lib-sieve/plugins/subaddress/subaddress.sieve new file mode 100644 index 0000000000000000000000000000000000000000..76031f7e3eeffb335ec3f6229f64eb0f53570959 --- /dev/null +++ b/src/lib-sieve/plugins/subaddress/subaddress.sieve @@ -0,0 +1,13 @@ +require "subaddress"; +require "fileinto"; + +if address :comparator "i;ascii-casemap" :user "from" "STEPHAN" { + discard; + + if address :domain :comparator "i;octet" "from" "drunksnipers.com" { + keep; + } + stop; +} + +keep; diff --git a/src/lib-sieve/plugins/vacation/ext-vacation.c b/src/lib-sieve/plugins/vacation/ext-vacation.c index 13383a0d16c7a188d79b5e8b6060c03bfc79508b..616c2652f4eaf393cd607d3521d223b036ea334b 100644 --- a/src/lib-sieve/plugins/vacation/ext-vacation.c +++ b/src/lib-sieve/plugins/vacation/ext-vacation.c @@ -199,17 +199,17 @@ static bool cmd_vacation_validate_handle_tag /* Command registration */ static const struct sieve_argument vacation_days_tag = - { "days", cmd_vacation_validate_days_tag, NULL }; + { "days", NULL, cmd_vacation_validate_days_tag, NULL }; static const struct sieve_argument vacation_subject_tag = - { "subject", cmd_vacation_validate_subject_tag, NULL }; + { "subject", NULL, cmd_vacation_validate_subject_tag, NULL }; static const struct sieve_argument vacation_from_tag = - { "from", cmd_vacation_validate_from_tag, NULL }; + { "from", NULL, cmd_vacation_validate_from_tag, NULL }; static const struct sieve_argument vacation_addresses_tag = - { "addresses", cmd_vacation_validate_addresses_tag, NULL }; + { "addresses", NULL, cmd_vacation_validate_addresses_tag, NULL }; static const struct sieve_argument vacation_mime_tag = - { "mime", cmd_vacation_validate_mime_tag, NULL }; + { "mime", NULL, cmd_vacation_validate_mime_tag, NULL }; static const struct sieve_argument vacation_handle_tag = - { "handle", cmd_vacation_validate_handle_tag, NULL }; + { "handle", NULL, cmd_vacation_validate_handle_tag, NULL }; enum cmd_vacation_optional { OPT_DAYS, diff --git a/src/lib-sieve/sieve-address-parts.c b/src/lib-sieve/sieve-address-parts.c index f0f7dabb628cde61a0cbc982011f278323ad658a..e553ed9fafd16da26fa10746b1ddddfe238ed54b 100644 --- a/src/lib-sieve/sieve-address-parts.c +++ b/src/lib-sieve/sieve-address-parts.c @@ -23,12 +23,12 @@ */ static void opr_address_part_emit - (struct sieve_binary *sbin, unsigned int code); + (struct sieve_binary *sbin, struct sieve_address_part *addrp); static void opr_address_part_emit_ext - (struct sieve_binary *sbin, int ext_id); + (struct sieve_binary *sbin, struct sieve_address_part *addrp, int ext_id); /* - * Comparator 'extension' + * Address-part 'extension' */ static int ext_my_id = -1; @@ -42,7 +42,7 @@ const struct sieve_extension address_part_extension = { addrp_extension_load, addrp_validator_load, NULL, - NULL, //addrp_interpreter_load, + addrp_interpreter_load, NULL, NULL }; @@ -55,11 +55,16 @@ static bool addrp_extension_load(int ext_id) /* * Validator context: - * name-based comparator registry. + * name-based address-part registry. */ +struct addrp_validator_registration { + int ext_id; + const struct sieve_address_part *address_part; +}; + struct addrp_validator_context { - struct hash_table *address_parts; + struct hash_table *registrations; }; static inline struct addrp_validator_context * @@ -68,25 +73,45 @@ static inline struct addrp_validator_context * return (struct addrp_validator_context *) sieve_validator_extension_get_context(validator, ext_my_id); } + +static void _sieve_address_part_register + (pool_t pool, struct addrp_validator_context *ctx, + const struct sieve_address_part *addrp, int ext_id) +{ + struct addrp_validator_registration *reg; + + reg = p_new(pool, struct addrp_validator_registration, 1); + reg->address_part = addrp; + reg->ext_id = ext_id; + + hash_insert(ctx->registrations, (void *) addrp->identifier, (void *) reg); +} void sieve_address_part_register - (struct sieve_validator *validator, const struct sieve_address_part *addrp) + (struct sieve_validator *validator, + const struct sieve_address_part *addrp, int ext_id) { + pool_t pool = sieve_validator_pool(validator); struct addrp_validator_context *ctx = get_validator_context(validator); - - hash_insert(ctx->address_parts, (void *) addrp->identifier, (void *) addrp); + + _sieve_address_part_register(pool, ctx, addrp, ext_id); } const struct sieve_address_part *sieve_address_part_find - (struct sieve_validator *validator, const char *addrp_name) + (struct sieve_validator *validator, const char *identifier, + int *ext_id) { struct addrp_validator_context *ctx = get_validator_context(validator); + struct addrp_validator_registration *reg = + (struct addrp_validator_registration *) + hash_lookup(ctx->registrations, identifier); - return (const struct sieve_address_part *) - hash_lookup(ctx->address_parts, addrp_name); + if ( ext_id != NULL ) *ext_id = reg->ext_id; + + return reg->address_part; } -static bool addrp_validator_load(struct sieve_validator *validator) +bool addrp_validator_load(struct sieve_validator *validator) { unsigned int i; pool_t pool = sieve_validator_pool(validator); @@ -94,15 +119,15 @@ static bool addrp_validator_load(struct sieve_validator *validator) struct addrp_validator_context *ctx = p_new(pool, struct addrp_validator_context, 1); - /* Setup comparator registry */ - ctx->address_parts = hash_create + /* Setup address-part registry */ + ctx->registrations = hash_create (pool, pool, 0, str_hash, (hash_cmp_callback_t *)strcmp); - /* Register core comparators */ + /* Register core address-parts */ for ( i = 0; i < sieve_core_address_parts_count; i++ ) { const struct sieve_address_part *addrp = sieve_core_address_parts[i]; - hash_insert(ctx->address_parts, (void *) addrp->identifier, (void *) addrp); + _sieve_address_part_register(pool, ctx, addrp, -1); } sieve_validator_extension_set_context(validator, ext_my_id, ctx); @@ -112,20 +137,67 @@ static bool addrp_validator_load(struct sieve_validator *validator) void sieve_address_parts_link_tags (struct sieve_validator *validator, - struct sieve_command_registration *cmd_reg, - unsigned int id_code) + struct sieve_command_registration *cmd_reg, unsigned int id_code) +{ + sieve_validator_register_tag + (validator, cmd_reg, &address_part_tag, id_code); +} + +/* + * Interpreter context: + */ + +struct addrp_interpreter_context { + ARRAY_DEFINE(addrp_extensions, + const struct sieve_address_part_extension *); +}; + +static inline struct addrp_interpreter_context * + get_interpreter_context(struct sieve_interpreter *interpreter) { - struct addrp_validator_context *ctx = get_validator_context(validator); - struct hash_iterate_context *itx = hash_iterate_init(ctx->address_parts); - void *key; - void *addrp; + return (struct addrp_interpreter_context *) + sieve_interpreter_extension_get_context(interpreter, ext_my_id); +} + +const struct sieve_address_part_extension *sieve_address_part_extension_get + (struct sieve_interpreter *interpreter, int ext_id) +{ + struct addrp_interpreter_context *ctx = get_interpreter_context(interpreter); - while ( hash_iterate(itx, &key, &addrp) ) { - sieve_validator_register_tag - (validator, cmd_reg, ((struct sieve_address_part *) addrp)->tag, id_code); + if ( (ctx != NULL) && (ext_id > 0) && (ext_id < (int) array_count(&ctx->addrp_extensions)) ) { + const struct sieve_address_part_extension * const *ext; + + ext = array_idx(&ctx->addrp_extensions, (unsigned int) ext_id); + + return *ext; } + + return NULL; +} + +void sieve_address_part_extension_set + (struct sieve_interpreter *interpreter, int ext_id, + const struct sieve_address_part_extension *ext) +{ + struct addrp_interpreter_context *ctx = get_interpreter_context(interpreter); + + array_idx_set(&ctx->addrp_extensions, (unsigned int) ext_id, &ext); +} + + +static bool addrp_interpreter_load(struct sieve_interpreter *interpreter) +{ + pool_t pool = sieve_interpreter_pool(interpreter); + + struct addrp_interpreter_context *ctx = + p_new(pool, struct addrp_interpreter_context, 1); + + /* Setup comparator registry */ + p_array_init(&ctx->addrp_extensions, pool, 4); - hash_iterate_deinit(&itx); + sieve_interpreter_extension_set_context(interpreter, ext_my_id, ctx); + + return TRUE; } /* @@ -140,12 +212,19 @@ struct sieve_operand address_part_operand = /* * Address-part tag */ + +static bool tag_address_part_is_instance_of + (struct sieve_validator *validator, const char *tag) +{ + return sieve_address_part_find(validator, tag, NULL) != NULL; +} static bool tag_address_part_validate - (struct sieve_validator *validator ATTR_UNUSED, + (struct sieve_validator *validator, struct sieve_ast_argument **arg, - struct sieve_command_context *cmd ATTR_UNUSED) + struct sieve_command_context *cmd) { + int ext_id; const struct sieve_address_part *addrp; /* Syntax: @@ -153,7 +232,8 @@ static bool tag_address_part_validate */ /* Get address_part from registry */ - addrp = sieve_address_part_find(validator, sieve_ast_argument_tag(*arg)); + addrp = sieve_address_part_find + (validator, sieve_ast_argument_tag(*arg), &ext_id); if ( addrp == NULL ) { sieve_command_validate_error(validator, cmd, @@ -164,8 +244,9 @@ static bool tag_address_part_validate return FALSE; } - /* Store comparator in context */ + /* Store address-part in context */ (*arg)->context = (void *) addrp; + (*arg)->ext_id = ext_id; /* Skip tag */ *arg = sieve_ast_argument_next(*arg); @@ -176,24 +257,26 @@ static bool tag_address_part_validate /* Code generation */ static void opr_address_part_emit - (struct sieve_binary *sbin, unsigned int code) + (struct sieve_binary *sbin, struct sieve_address_part *addrp) { (void) sieve_operand_emit_code(sbin, SIEVE_OPERAND_ADDRESS_PART); - (void) sieve_binary_emit_byte(sbin, code); + (void) sieve_binary_emit_byte(sbin, addrp->code); } static void opr_address_part_emit_ext - (struct sieve_binary *sbin, int ext_id) + (struct sieve_binary *sbin, struct sieve_address_part *addrp, int ext_id) { - unsigned char cmp_code = SIEVE_ADDRESS_PART_CUSTOM + + unsigned char addrp_code = SIEVE_ADDRESS_PART_CUSTOM + sieve_binary_extension_get_index(sbin, ext_id); (void) sieve_operand_emit_code(sbin, SIEVE_OPERAND_ADDRESS_PART); - (void) sieve_binary_emit_byte(sbin, cmp_code); + (void) sieve_binary_emit_byte(sbin, addrp_code); + (void) sieve_binary_emit_byte(sbin, addrp->ext_code); } const struct sieve_address_part *sieve_opr_address_part_read - (struct sieve_binary *sbin, sieve_size_t *address) + (struct sieve_interpreter *interpreter, + struct sieve_binary *sbin, sieve_size_t *address) { unsigned int addrp_code; const struct sieve_operand *operand = sieve_operand_read(sbin, address); @@ -208,25 +291,39 @@ const struct sieve_address_part *sieve_opr_address_part_read else return NULL; } else { - /*const struct sieve_extension *ext = - sieve_binary_get_extension(sbin, cmp_code - SIEVE_ADDRESS_PART_CUSTOM); - - if ( ext != NULL ) - return (const struct sieve_address_part *) - sieve_interpreter_registry_get(addrp_registry, ext); - else*/ - return NULL; + int ext_id = -1; + const struct sieve_address_part_extension *ap_ext; + + if ( sieve_binary_extension_get_by_index(sbin, + addrp_code - SIEVE_ADDRESS_PART_CUSTOM, &ext_id) == NULL ) + return NULL; + + ap_ext = sieve_address_part_extension_get(interpreter, ext_id); + + if ( ap_ext != NULL ) { + unsigned int code; + if ( ap_ext->address_part != NULL ) + return ap_ext->address_part; + + if ( sieve_binary_read_byte(sbin, address, &code) && + ap_ext->get_part != NULL ) + return ap_ext->get_part(code); + } else { + i_info("Unknown address-part modifier %d.", addrp_code); + } } } - return NULL; + return NULL; } -bool sieve_opr_address_part_dump(struct sieve_binary *sbin, sieve_size_t *address) +bool sieve_opr_address_part_dump + (struct sieve_interpreter *interpreter, + struct sieve_binary *sbin, sieve_size_t *address) { sieve_size_t pc = *address; const struct sieve_address_part *addrp = - sieve_opr_address_part_read(sbin, address); + sieve_opr_address_part_read(interpreter, sbin, address); if ( addrp == NULL ) return FALSE; @@ -241,16 +338,16 @@ static bool tag_address_part_generate struct sieve_command_context *cmd ATTR_UNUSED) { struct sieve_binary *sbin = sieve_generator_get_binary(generator); - struct sieve_address_part *addrp = + struct sieve_address_part *addrp = (struct sieve_address_part *) (*arg)->context; if ( addrp->extension == NULL ) { if ( addrp->code < SIEVE_ADDRESS_PART_CUSTOM ) - opr_address_part_emit(sbin, addrp->code); + opr_address_part_emit(sbin, addrp); else return FALSE; } else { - //opr_comparator_emit_ext(sbin, cmp->extension); + opr_address_part_emit_ext(sbin, addrp, (*arg)->ext_id); } *arg = sieve_ast_argument_next(*arg); @@ -263,8 +360,9 @@ static bool tag_address_part_generate */ bool sieve_address_stringlist_match - (struct sieve_address_part *addrp, struct sieve_coded_stringlist *key_list, - struct sieve_comparator *cmp, const char *data) + (const struct sieve_address_part *addrp, + struct sieve_coded_stringlist *key_list, + const struct sieve_comparator *cmp, const char *data) { bool matched = FALSE; const struct message_address *addr; @@ -281,7 +379,7 @@ bool sieve_address_stringlist_match const char *part; i_assert(addr->mailbox != NULL); - + part = addrp->extract_from(addr); if ( sieve_stringlist_match(key_list, part, cmp) ) @@ -299,14 +397,14 @@ bool sieve_address_stringlist_match /* * Core address-part modifiers */ - -const struct sieve_argument address_localpart_tag = - { "localpart", tag_address_part_validate, tag_address_part_generate }; -const struct sieve_argument address_domain_tag = - { "domain", tag_address_part_validate, tag_address_part_generate }; -const struct sieve_argument address_all_tag = - { "all", tag_address_part_validate, tag_address_part_generate }; +const struct sieve_argument address_part_tag = { + NULL, + tag_address_part_is_instance_of, + tag_address_part_validate, + tag_address_part_generate +}; + static const char *addrp_all_extract_from (const struct message_address *address) { @@ -327,25 +425,25 @@ static const char *addrp_localpart_extract_from const struct sieve_address_part all_address_part = { "all", - &address_all_tag, SIEVE_ADDRESS_PART_ALL, NULL, + 0, addrp_all_extract_from }; const struct sieve_address_part local_address_part = { "localpart", - &address_localpart_tag, SIEVE_ADDRESS_PART_LOCAL, NULL, + 0, addrp_localpart_extract_from }; const struct sieve_address_part domain_address_part = { "domain", - &address_domain_tag, SIEVE_ADDRESS_PART_DOMAIN, NULL, + 0, addrp_domain_extract_from }; @@ -353,6 +451,7 @@ const struct sieve_address_part *sieve_core_address_parts[] = { &all_address_part, &local_address_part, &domain_address_part }; -const unsigned int sieve_core_address_parts_count = N_ELEMENTS(sieve_core_address_parts); +const unsigned int sieve_core_address_parts_count = + N_ELEMENTS(sieve_core_address_parts); diff --git a/src/lib-sieve/sieve-address-parts.h b/src/lib-sieve/sieve-address-parts.h index ebc560e0c7d15ad2928922355947cfa1aa65e6e4..a45c3620a8e789b9d5dfd6e3526efafcde761eb5 100644 --- a/src/lib-sieve/sieve-address-parts.h +++ b/src/lib-sieve/sieve-address-parts.h @@ -14,38 +14,58 @@ enum sieve_address_part_code { struct sieve_address_part { const char *identifier; - const struct sieve_argument *tag; enum sieve_address_part_code code; + const struct sieve_extension *extension; + unsigned int ext_code; const char *(*extract_from)(const struct message_address *address); }; +struct sieve_address_part_extension { + /* Either a single addr-part in this extension ... */ + const struct sieve_address_part *address_part; + + /* ... or multiple: then the extension must handle emit/read */ + const struct sieve_address_part *(*get_part) + (unsigned int code); +}; + void sieve_address_parts_link_tags (struct sieve_validator *validator, struct sieve_command_registration *cmd_reg, unsigned int id_code); void sieve_address_part_register - (struct sieve_validator *validator, const struct sieve_address_part *addrp); + (struct sieve_validator *validator, + const struct sieve_address_part *addrp, int ext_id); const struct sieve_address_part *sieve_address_part_find - (struct sieve_validator *validator, const char *addrp_name); + (struct sieve_validator *validator, const char *identifier, + int *ext_id); +void sieve_address_part_extension_set + (struct sieve_interpreter *interpreter, int ext_id, + const struct sieve_address_part_extension *ext); + +extern const struct sieve_argument address_part_tag; -const struct sieve_address_part all_address_part; -const struct sieve_address_part local_address_part; -const struct sieve_address_part domain_address_part; +extern const struct sieve_address_part all_address_part; +extern const struct sieve_address_part local_address_part; +extern const struct sieve_address_part domain_address_part; extern const struct sieve_address_part *sieve_core_address_parts[]; extern const unsigned int sieve_core_address_parts_count; const struct sieve_address_part *sieve_opr_address_part_read - (struct sieve_binary *sbin, sieve_size_t *address); + (struct sieve_interpreter *interpreter, + struct sieve_binary *sbin, sieve_size_t *address); bool sieve_opr_address_part_dump - (struct sieve_binary *sbin, sieve_size_t *address); + (struct sieve_interpreter *interpreter, + struct sieve_binary *sbin, sieve_size_t *address); bool sieve_address_stringlist_match - (struct sieve_address_part *addrp, struct sieve_coded_stringlist *key_list, - struct sieve_comparator *cmp, const char *data); + (const struct sieve_address_part *addrp, + struct sieve_coded_stringlist *key_list, + const struct sieve_comparator *cmp, const char *data); #endif /* __SIEVE_ADDRESS_PARTS_H */ diff --git a/src/lib-sieve/sieve-ast.h b/src/lib-sieve/sieve-ast.h index 525bd293e4259142f5451d8acdfe248d6770a38e..bfc60ec3e23d5f6255e4ab6303b8ef525013e83e 100644 --- a/src/lib-sieve/sieve-ast.h +++ b/src/lib-sieve/sieve-ast.h @@ -87,6 +87,9 @@ struct sieve_ast_argument { /* Context data associated with this ast element */ void *context; + + /* Indicates whether this argument is part of which extension */ + int ext_id; }; struct sieve_ast_list { diff --git a/src/lib-sieve/sieve-binary.c b/src/lib-sieve/sieve-binary.c index 552edc0923c3dd553d11edd681cffb0c65592348..febbc489119aa2f1b1751766937b1867b779c0ab 100644 --- a/src/lib-sieve/sieve-binary.c +++ b/src/lib-sieve/sieve-binary.c @@ -123,6 +123,12 @@ int sieve_binary_extension_get_index return -1; } +int sieve_binary_extensions_count(struct sieve_binary *sbin) +{ + return (int) array_count(&sbin->extensions); +} + + /* * Emission functions */ diff --git a/src/lib-sieve/sieve-binary.h b/src/lib-sieve/sieve-binary.h index fcea7fe2b3edf6dd6fd295f3fbe154361fd203ec..49440d1ce5d668beb5652576fa975d8d54a7b621 100644 --- a/src/lib-sieve/sieve-binary.h +++ b/src/lib-sieve/sieve-binary.h @@ -24,6 +24,7 @@ const struct sieve_extension *sieve_binary_extension_get_by_index (struct sieve_binary *sbin, int index, int *ext_id); int sieve_binary_extension_get_index (struct sieve_binary *sbin, int ext_id); +int sieve_binary_extensions_count(struct sieve_binary *sbin); /* * Code emission diff --git a/src/lib-sieve/sieve-commands.c b/src/lib-sieve/sieve-commands.c index 44b6772c579969a2a5344c01bb8a46af137d64c1..aea83eeeb7bb6d9e9bbd45fbf4928fa0b931fa51 100644 --- a/src/lib-sieve/sieve-commands.c +++ b/src/lib-sieve/sieve-commands.c @@ -19,11 +19,11 @@ static bool arg_string_list_generate(struct sieve_generator *generator, struct s struct sieve_command_context *context); const struct sieve_argument number_argument = - { "@number", NULL, arg_number_generate }; + { "@number", NULL, NULL, arg_number_generate }; const struct sieve_argument string_argument = - { "@string", NULL, arg_string_generate }; + { "@string", NULL, NULL, arg_string_generate }; const struct sieve_argument string_list_argument = - { "@string-list", NULL, arg_string_list_generate }; + { "@string-list", NULL, NULL, arg_string_list_generate }; static bool arg_number_generate(struct sieve_generator *generator, struct sieve_ast_argument **arg, struct sieve_command_context *context ATTR_UNUSED) diff --git a/src/lib-sieve/sieve-commands.h b/src/lib-sieve/sieve-commands.h index 128289ba4073ba347840ad92547940b7a7621acb..0c51119978cab9ef6ec8946b9cf698ebde156d49 100644 --- a/src/lib-sieve/sieve-commands.h +++ b/src/lib-sieve/sieve-commands.h @@ -13,8 +13,10 @@ struct sieve_argument { const char *identifier; + bool (*is_instance_of)(struct sieve_validator *validator, const char *tag); bool (*validate)(struct sieve_validator *validator, struct sieve_ast_argument **arg, struct sieve_command_context *context); + bool (*generate)(struct sieve_generator *generator, struct sieve_ast_argument **arg, struct sieve_command_context *context); }; diff --git a/src/lib-sieve/sieve-comparators.c b/src/lib-sieve/sieve-comparators.c index 7cd416a769224188c60264085c48a3e93a47bf59..89f40b932a54bbe4ff8a6b22ad5ce02f513957be 100644 --- a/src/lib-sieve/sieve-comparators.c +++ b/src/lib-sieve/sieve-comparators.c @@ -151,7 +151,7 @@ static bool cmp_interpreter_load(struct sieve_interpreter *interpreter) p_new(pool, struct cmp_interpreter_context, 1); /* Setup comparator registry */ - p_array_init(&ctx->cmp_extensions, default_pool, 4); + p_array_init(&ctx->cmp_extensions, pool, 4); sieve_interpreter_extension_set_context(interpreter, ext_my_id, ctx); @@ -177,7 +177,7 @@ static bool tag_comparator_generate struct sieve_command_context *cmd); const struct sieve_argument comparator_tag = - { "comparator", tag_comparator_validate, tag_comparator_generate }; + { "comparator", NULL, tag_comparator_validate, tag_comparator_generate }; static bool tag_comparator_validate (struct sieve_validator *validator, struct sieve_ast_argument **arg, diff --git a/src/lib-sieve/sieve-extensions.c b/src/lib-sieve/sieve-extensions.c index 438d02b54a3a3b964d9364a96529967a1762cd0b..935ceda1239f9fb2d14d06b954963453592681f7 100644 --- a/src/lib-sieve/sieve-extensions.c +++ b/src/lib-sieve/sieve-extensions.c @@ -24,10 +24,14 @@ extern const struct sieve_extension envelope_extension; /* Plugins (FIXME: make this dynamic) */ extern const struct sieve_extension vacation_extension; +extern const struct sieve_extension subaddress_extension; const struct sieve_extension *sieve_core_extensions[] = { &comparator_extension, &address_part_extension, - &fileinto_extension, &reject_extension, &envelope_extension, &vacation_extension + &fileinto_extension, &reject_extension, &envelope_extension, + + /* 'Plugins' */ + &vacation_extension, &subaddress_extension }; const unsigned int sieve_core_extensions_count = @@ -78,7 +82,8 @@ static struct hash_table *extension_index; static void sieve_extensions_init_registry(void) { p_array_init(&extensions, default_pool, 4); - extension_index = hash_create(default_pool, default_pool, 0, NULL, NULL); + extension_index = hash_create + (default_pool, default_pool, 0, str_hash, (hash_cmp_callback_t *)strcmp); } int sieve_extension_register(const struct sieve_extension *extension) diff --git a/src/lib-sieve/sieve-extensions.h b/src/lib-sieve/sieve-extensions.h index 0f1d27fe2a786607905927e1ac7057f51ca64279..9334747ed625c2e3140d0e1221a3b5075b3a6abb 100644 --- a/src/lib-sieve/sieve-extensions.h +++ b/src/lib-sieve/sieve-extensions.h @@ -9,7 +9,7 @@ struct sieve_extension { bool (*load)(int ext_id); - bool (*validator_load)(struct sieve_validator *validator); + bool (*validator_load)(struct sieve_validator *validator); bool (*generator_load)(struct sieve_generator *generator); bool (*interpreter_load)(struct sieve_interpreter *interpreter); diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c index e323bc14fc0bd6f7eb704e48d3dfe4cd52b3adc9..68035454f7c340ecc17ff6b3924849a1e577fdc5 100644 --- a/src/lib-sieve/sieve-interpreter.c +++ b/src/lib-sieve/sieve-interpreter.c @@ -22,7 +22,7 @@ struct sieve_interpreter { struct sieve_binary *binary; /* Object registries */ - ARRAY_DEFINE(ext_contexts, void); + ARRAY_DEFINE(ext_contexts, void *); /* Execution status */ sieve_size_t pc; @@ -33,8 +33,12 @@ struct sieve_interpreter { struct mail *mail; }; +extern struct sieve_extension comparator_extension; +extern struct sieve_extension address_part_extension; + struct sieve_interpreter *sieve_interpreter_create(struct sieve_binary *binary) { + int i; pool_t pool; struct sieve_interpreter *interp; @@ -48,8 +52,20 @@ struct sieve_interpreter *sieve_interpreter_create(struct sieve_binary *binary) interp->pc = 0; - array_create(&interp->ext_contexts, pool, sizeof(void *), - sieve_extensions_get_count()); + p_array_init(&interp->ext_contexts, pool, 4); + //array_create(&interp->ext_contexts, pool, sizeof(void *), + // sieve_extensions_get_count()); + + (void)comparator_extension.interpreter_load(interp); + (void)address_part_extension.interpreter_load(interp); + + for ( i = 0; i < sieve_binary_extensions_count(binary); i++ ) { + const struct sieve_extension *ext = + sieve_binary_extension_get_by_index(binary, i, NULL); + + if ( ext->interpreter_load != NULL ) + ext->interpreter_load(interp); + } return interp; } @@ -71,16 +87,20 @@ inline pool_t sieve_interpreter_pool(struct sieve_interpreter *interp) inline void sieve_interpreter_extension_set_context (struct sieve_interpreter *interpreter, int ext_id, void *context) { - array_idx_set(&interpreter->ext_contexts, (unsigned int) ext_id, context); + array_idx_set(&interpreter->ext_contexts, (unsigned int) ext_id, &context); } inline const void *sieve_interpreter_extension_get_context (struct sieve_interpreter *interpreter, int ext_id) { - if ( ext_id < 0 || ext_id > (int) array_count(&interpreter->ext_contexts) ) + void * const *ctx; + + if ( ext_id < 0 || ext_id >= (int) array_count(&interpreter->ext_contexts) ) return NULL; - return array_idx(&interpreter->ext_contexts, (unsigned int) ext_id); + ctx = array_idx(&interpreter->ext_contexts, (unsigned int) ext_id); + + return *ctx; } diff --git a/src/lib-sieve/sieve-validator.c b/src/lib-sieve/sieve-validator.c index e870f4c241ad83ce82d817d9d33ccdb4f2a1d4d3..cada9ae852aa1669ca74a365b4469fc30a0b6f25 100644 --- a/src/lib-sieve/sieve-validator.c +++ b/src/lib-sieve/sieve-validator.c @@ -82,7 +82,6 @@ struct sieve_validator *sieve_validator_create(struct sieve_ast *ast, struct sie sieve_validator_register_core_commands(validator); sieve_validator_register_core_tests(validator); - return validator; } @@ -101,10 +100,13 @@ inline pool_t sieve_validator_pool(struct sieve_validator *validator) /* Command registry */ +struct sieve_tag_registration; + struct sieve_command_registration { const struct sieve_command *command; struct hash_table *tags; + ARRAY_DEFINE(instanced_tags, struct sieve_tag_registration *); }; /* Dummy function */ @@ -116,10 +118,10 @@ static bool _cmd_unknown_validate return FALSE; } -static const struct sieve_command unknown_command = { "", SCT_COMMAND, NULL, _cmd_unknown_validate, NULL, NULL }; -static const struct sieve_command_registration unknown_command_registration = { &unknown_command, NULL }; -static const struct sieve_command unknown_test = { "", SCT_TEST, NULL, _cmd_unknown_validate, NULL, NULL }; -static const struct sieve_command_registration unknown_test_registration = { &unknown_test, NULL }; +static const struct sieve_command unknown_command = + { "", SCT_COMMAND, NULL, _cmd_unknown_validate, NULL, NULL }; +static const struct sieve_command unknown_test = + { "", SCT_TEST, NULL, _cmd_unknown_validate, NULL, NULL }; static void sieve_validator_register_core_tests(struct sieve_validator *validator) { @@ -139,26 +141,37 @@ static void sieve_validator_register_core_commands(struct sieve_validator *valid } } -void sieve_validator_register_command(struct sieve_validator *validator, const struct sieve_command *command) +static void _sieve_validator_register_command + (struct sieve_validator *validator, const struct sieve_command *command, + const char *identifier) { - struct sieve_command_registration *record = p_new(validator->pool, struct sieve_command_registration, 1); + struct sieve_command_registration *record = + p_new(validator->pool, struct sieve_command_registration, 1); record->command = command; record->tags = NULL; - hash_insert(validator->commands, (void *) command->identifier, (void *) record); + hash_insert(validator->commands, (void *) identifier, (void *) record); if ( command->registered != NULL ) { command->registered(validator, record); } } -static void sieve_validator_register_unknown_command(struct sieve_validator *validator, const char *command) -{ - hash_insert(validator->commands, (void *) command, (void *) &unknown_command_registration); +void sieve_validator_register_command + (struct sieve_validator *validator, const struct sieve_command *command) +{ + _sieve_validator_register_command(validator, command, command->identifier); +} + +static void sieve_validator_register_unknown_command + (struct sieve_validator *validator, const char *command) +{ + _sieve_validator_register_command(validator, &unknown_command, command); } -static void sieve_validator_register_unknown_test(struct sieve_validator *validator, const char *test) +static void sieve_validator_register_unknown_test + (struct sieve_validator *validator, const char *test) { - hash_insert(validator->commands, (void *) test, (void *) &unknown_test_registration); + _sieve_validator_register_command(validator, &unknown_test, test); } static struct sieve_command_registration *sieve_validator_find_command_registration @@ -193,7 +206,8 @@ static bool _unknown_tag_validate return FALSE; } -static const struct sieve_argument _unknown_tag = { "", _unknown_tag_validate, NULL }; +static const struct sieve_argument _unknown_tag = + { "", NULL, _unknown_tag_validate, NULL }; static void _sieve_validator_register_tag (struct sieve_validator *validator, struct sieve_command_registration *cmd_reg, @@ -217,7 +231,19 @@ void sieve_validator_register_tag (struct sieve_validator *validator, struct sieve_command_registration *cmd_reg, const struct sieve_argument *tag, unsigned int id_code) { - _sieve_validator_register_tag(validator, cmd_reg, tag, tag->identifier, id_code); + if ( tag->is_instance_of == NULL ) + _sieve_validator_register_tag(validator, cmd_reg, tag, tag->identifier, id_code); + else { + struct sieve_tag_registration *reg = + p_new(validator->pool, struct sieve_tag_registration, 1); + reg->tag = tag; + reg->id_code = id_code; + + if ( !array_is_created(&cmd_reg->instanced_tags) ) + p_array_init(&cmd_reg->instanced_tags, validator->pool, 1); + + array_append(&cmd_reg->instanced_tags, ®, 1); + } } static void sieve_validator_register_unknown_tag @@ -228,21 +254,39 @@ static void sieve_validator_register_unknown_tag } static const struct sieve_argument *sieve_validator_find_tag - (struct sieve_command_registration *cmd_reg, const char *tag, unsigned int *id_code) + (struct sieve_validator *validator, + struct sieve_command_registration *cmd_reg, + const char *tag, unsigned int *id_code) { + unsigned int i; const struct sieve_tag_registration *reg; *id_code = 0; - if ( cmd_reg->tags == NULL ) return NULL; - - reg = (const struct sieve_tag_registration *) hash_lookup(cmd_reg->tags, tag); - - if ( reg == NULL )return NULL; + if ( cmd_reg->tags != NULL ) { + reg = (const struct sieve_tag_registration *) + hash_lookup(cmd_reg->tags, tag); - *id_code = reg->id_code; + if ( reg != NULL ) { + *id_code = reg->id_code; + return reg->tag; + } + } + + /* Not found so far, try the instanced tags */ + if ( array_is_created(&cmd_reg->instanced_tags) ) { + for ( i = 0; i < array_count(&cmd_reg->instanced_tags); i++ ) { + struct sieve_tag_registration * const *reg = + array_idx(&cmd_reg->instanced_tags, i); + + if ( (*reg)->tag != NULL && (*reg)->tag->is_instance_of(validator, tag) ) { + *id_code = (*reg)->id_code; + return (*reg)->tag; + } + } + } - return reg->tag; + return NULL; } /* Extension support */ @@ -301,11 +345,11 @@ static bool sieve_validate_match_type_tag } static const struct sieve_argument match_is_tag = - { "is", sieve_validate_match_type_tag, NULL }; + { "is", NULL, sieve_validate_match_type_tag, NULL }; static const struct sieve_argument match_contains_tag = - { "contains", sieve_validate_match_type_tag, NULL }; + { "contains", NULL, sieve_validate_match_type_tag, NULL }; static const struct sieve_argument match_matches_tag = - { "matches", sieve_validate_match_type_tag, NULL }; + { "matches", NULL, sieve_validate_match_type_tag, NULL }; void sieve_validator_link_match_type_tags (struct sieve_validator *validator, struct sieve_command_registration *cmd_reg, @@ -338,13 +382,15 @@ bool sieve_validate_command_arguments if ( cmd_reg == NULL ) { sieve_command_validate_error( - validator, cmd, - "!!BUG!!: the '%s' %s seemed to be known before, but somehow its registration got lost", - cmd->command->identifier, sieve_command_type_name(cmd->command) - ); - i_error("BUG: the '%s' %s seemed to be known before, but somehow its registration got lost", - cmd->command->identifier, sieve_command_type_name(cmd->command) - ); + validator, cmd, + "!!BUG!!: the '%s' %s seemed to be known before, " + "but somehow its registration got lost", + cmd->command->identifier, sieve_command_type_name(cmd->command) + ); + i_error("BUG: the '%s' %s seemed to be known before, " + "but somehow its registration got lost", + cmd->command->identifier, sieve_command_type_name(cmd->command) + ); return FALSE; } } @@ -353,18 +399,22 @@ bool sieve_validate_command_arguments while ( sieve_ast_argument_type(arg) == SAAT_TAG ) { unsigned int id_code; const struct sieve_argument *tag = - sieve_validator_find_tag(cmd_reg, sieve_ast_argument_tag(arg), &id_code); + sieve_validator_find_tag + (validator, cmd_reg, sieve_ast_argument_tag(arg), &id_code); if ( tag == NULL ) { sieve_command_validate_error(validator, cmd, - "unknown tagged argument ':%s' for the %s %s (reported only once at first occurence)", - sieve_ast_argument_tag(arg), cmd->command->identifier, sieve_command_type_name(cmd->command)); - sieve_validator_register_unknown_tag(validator, cmd_reg, sieve_ast_argument_tag(arg)); - return FALSE; + "unknown tagged argument ':%s' for the %s %s " + "(reported only once at first occurence)", + sieve_ast_argument_tag(arg), cmd->command->identifier, + sieve_command_type_name(cmd->command)); + sieve_validator_register_unknown_tag + (validator, cmd_reg, sieve_ast_argument_tag(arg)); + return FALSE; } /* Check whether previously tagged as unknown */ - if ( *(tag->identifier) == '\0' ) + if ( tag->identifier != NULL && *(tag->identifier) == '\0' ) return FALSE; /* Assign the tagged argument type to the ast for later reference (in generator) */ @@ -486,12 +536,16 @@ bool sieve_validate_command_block(struct sieve_validator *validator, struct siev if ( block_required ) { if ( !cmd->ast_node->block ) { sieve_command_validate_error - ( validator, cmd, "the %s command requires a command block, but it is missing", cmd->command->identifier ); + ( validator, cmd, + "the %s command requires a command block, but it is missing", + cmd->command->identifier ); return FALSE; } } else if ( !block_allowed && cmd->ast_node->block ) { sieve_command_validate_error - ( validator, cmd, "the %s command does not accept a command block, but one is specified anyway", cmd->command->identifier ); + ( validator, cmd, + "the %s command does not accept a command block, but one is specified anyway", + cmd->command->identifier ); return FALSE; } @@ -518,7 +572,9 @@ static bool sieve_validate_test(struct sieve_validator *validator, struct sieve_ /* Identifier = "" when the command was previously marked as unknown */ if ( *(test->identifier) != '\0' ) { if ( test->type != SCT_TEST ) { - sieve_validator_error(validator, tst_node, "attempted to use command '%s' as test", tst_node->identifier); + sieve_validator_error( + validator, tst_node, + "attempted to use command '%s' as test", tst_node->identifier); result = FALSE; } else { struct sieve_command_context *ctx = sieve_command_context_create(tst_node, test); @@ -540,7 +596,9 @@ static bool sieve_validate_test(struct sieve_validator *validator, struct sieve_ result = FALSE; } else { - sieve_validator_error(validator, tst_node, "unknown test '%s' (only reported once at first occurence)", tst_node->identifier); + sieve_validator_error(validator, tst_node, + "unknown test '%s' (only reported once at first occurence)", + tst_node->identifier); sieve_validator_register_unknown_test(validator, tst_node->identifier); result = FALSE; @@ -602,7 +660,10 @@ static bool sieve_validate_command(struct sieve_validator *validator, struct sie result = FALSE; } else { - sieve_validator_error(validator, cmd_node, "unknown command '%s' (only reported once at first occurence)", cmd_node->identifier); + sieve_validator_error( + validator, cmd_node, + "unknown command '%s' (only reported once at first occurence)", + cmd_node->identifier); sieve_validator_register_unknown_command(validator, cmd_node->identifier); result = FALSE; diff --git a/src/lib-sieve/tst-address.c b/src/lib-sieve/tst-address.c index 5e828aece8690547737602c70d5cacb3db9064cd..bc0801655fbae34dff2d8c7b33e4fd4bd4259442 100644 --- a/src/lib-sieve/tst-address.c +++ b/src/lib-sieve/tst-address.c @@ -113,7 +113,7 @@ static bool tst_address_opcode_dump case OPT_MATCH_TYPE: break; case OPT_ADDRESS_PART: - if ( !sieve_opr_address_part_dump(sbin, address) ) + if ( !sieve_opr_address_part_dump(interp, sbin, address) ) return FALSE; break; default: @@ -155,7 +155,7 @@ static bool tst_address_opcode_execute case OPT_MATCH_TYPE: break; case OPT_ADDRESS_PART: - if ( (addrp = sieve_opr_address_part_read(sbin, address)) == NULL ) + if ( (addrp = sieve_opr_address_part_read(interp, sbin, address)) == NULL ) return FALSE; break; default: diff --git a/src/lib-sieve/tst-size.c b/src/lib-sieve/tst-size.c index 9c665070797fe5b4a7a7c2e296b903a9c012de50..2ddca289ca193e4e409d5c32bc687787fe47c9eb 100644 --- a/src/lib-sieve/tst-size.c +++ b/src/lib-sieve/tst-size.c @@ -77,9 +77,9 @@ static bool tst_size_validate_under_tag /* Test registration */ static const struct sieve_argument size_over_tag = - { "over", tst_size_validate_over_tag, NULL }; + { "over", NULL, tst_size_validate_over_tag, NULL }; static const struct sieve_argument size_under_tag = - { "under", tst_size_validate_under_tag, NULL }; + { "under", NULL, tst_size_validate_under_tag, NULL }; bool tst_size_registered(struct sieve_validator *validator, struct sieve_command_registration *cmd_reg) { diff --git a/src/sieve-bin/Makefile.am b/src/sieve-bin/Makefile.am index 398055a895a17bb481b6c00081257482154f844c..ebb5b7dde90f982ba5e71206140080f59740e2df 100644 --- a/src/sieve-bin/Makefile.am +++ b/src/sieve-bin/Makefile.am @@ -13,8 +13,10 @@ AM_CPPFLAGS = \ plugin_dir = \ $(top_srcdir)/src/lib-sieve/plugins +# These are not actual plugins just yet... plugins = \ - $(plugin_dir)/vacation/lib_ext_vacation.a + $(plugin_dir)/vacation/lib_ext_vacation.a \ + $(plugin_dir)/subaddress/lib_ext_subaddress.a sievec_LDFLAGS = -export-dynamic -Wl,--start-group sieve_test_LDFLAGS = -export-dynamic -Wl,--start-group